- added instructions how to update the online documentation
[bochs-mirror.git] / config.cc
blob73f902e0f924486ab464105309f16528bf21181e
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: config.cc,v 1.141 2008/12/11 18:01:54 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "bochs.h"
28 #include "iodev/iodev.h"
29 #include <assert.h>
31 #ifdef HAVE_LOCALE_H
32 #include <locale.h>
33 #endif
35 #if defined(macintosh)
36 // Work around a bug in SDL 1.2.4 on MacOS X, which redefines getenv to
37 // SDL_getenv, but then neglects to provide SDL_getenv. It happens
38 // because we are defining -Dmacintosh.
39 #undef getenv
40 #endif
43 int bochsrc_include_count = 0;
45 #define LOG_THIS genlog->
47 extern bx_debug_t bx_dbg;
49 static const char *get_builtin_variable(const char *varname);
50 static int parse_line_unformatted(const char *context, char *line);
51 static int 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 switch (val) {
140 case BX_FLOPPY_1_2:
141 case BX_FLOPPY_1_44:
142 case BX_FLOPPY_2_88:
143 device = val;
144 break;
145 case BX_FLOPPY_720K:
146 device = BX_FLOPPY_1_44;
147 break;
148 default:
149 device = BX_FLOPPY_1_2;
151 SIM->get_param_enum(BXPN_FLOPPYA_DEVTYPE)->set(device);
154 } else if (!strcmp(pname, BXPN_FLOPPYB_TYPE)) {
155 if (set) {
156 if (val == BX_FLOPPY_AUTO) {
157 val = get_floppy_type_from_image(SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr());
158 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(val);
159 } else if (!SIM->get_init_done()) {
160 switch (val) {
161 case BX_FLOPPY_1_2:
162 case BX_FLOPPY_1_44:
163 case BX_FLOPPY_2_88:
164 device = val;
165 break;
166 case BX_FLOPPY_720K:
167 device = BX_FLOPPY_1_44;
168 break;
169 default:
170 device = BX_FLOPPY_1_2;
172 SIM->get_param_enum(BXPN_FLOPPYB_DEVTYPE)->set(device);
175 } else if (!strcmp(pname, BXPN_FLOPPYA_STATUS)) {
176 if ((set) && (SIM->get_init_done())) {
177 DEV_floppy_set_media_status(0, val == BX_INSERTED);
178 bx_gui->update_drive_status_buttons();
180 } else if (!strcmp(pname, BXPN_FLOPPYB_STATUS)) {
181 if ((set) && (SIM->get_init_done())) {
182 DEV_floppy_set_media_status(1, val == BX_INSERTED);
183 bx_gui->update_drive_status_buttons();
185 } else {
186 BX_PANIC(("bx_param_handler called with unknown parameter '%s'", pname));
187 return -1;
190 return val;
193 const char *bx_param_string_handler(bx_param_string_c *param, int set, const char *val, int maxlen)
195 char pname[BX_PATHNAME_LEN];
196 Bit8u channel, device;
198 int empty = 0;
199 if ((strlen(val) < 1) || !strcmp ("none", val)) {
200 empty = 1;
201 val = "none";
203 bx_list_c *base = (bx_list_c*) param->get_parent();
204 base->get_param_path(pname, BX_PATHNAME_LEN);
205 if (!strncmp(pname, "ata.", 4)) {
206 channel = pname[4] - '0';
207 if (!strcmp(base->get_name(), "master")) {
208 device = 0;
209 } else {
210 device = 1;
212 if (!strcmp(param->get_name(), "path")) {
213 if (set==1) {
214 if (SIM->get_init_done()) {
215 Bit32u handle = DEV_hd_get_device_handle(channel, device);
216 if (empty) {
217 DEV_hd_set_cd_media_status(handle, 0);
218 bx_gui->update_drive_status_buttons();
219 } else {
220 if (!SIM->get_param_num("present", base)->get()) {
221 BX_ERROR(("Cannot add a cdrom drive at runtime"));
222 SIM->get_param_num("present", base)->set(0);
224 if (SIM->get_param_num("type", base)->get() != BX_ATA_DEVICE_CDROM) {
225 BX_ERROR(("Device is not a cdrom drive"));
226 SIM->get_param_num("present", base)->set(0);
229 if (DEV_hd_present() &&
230 (SIM->get_param_num("status", base)->get() == BX_INSERTED) &&
231 (SIM->get_param_num("type", base)->get() == BX_ATA_DEVICE_CDROM)) {
232 // tell the device model that we removed, then inserted the cd
233 DEV_hd_set_cd_media_status(handle, 0);
234 DEV_hd_set_cd_media_status(handle, 1);
239 } else {
240 param->get_param_path(pname, BX_PATHNAME_LEN);
241 if (!strcmp(pname, BXPN_SCREENMODE)) {
242 if (set==1) {
243 BX_INFO(("Screen mode changed to %s", val));
245 } else if (!strcmp(pname, BXPN_FLOPPYA_PATH)) {
246 if (set==1) {
247 if (SIM->get_init_done()) {
248 if (empty) {
249 DEV_floppy_set_media_status(0, 0);
250 bx_gui->update_drive_status_buttons();
251 } else {
252 if (!SIM->get_param_num(BXPN_FLOPPYA_TYPE)->get_enabled()) {
253 BX_ERROR(("Cannot add a floppy drive at runtime"));
254 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set("none");
257 if ((DEV_floppy_present()) &&
258 (SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->get() == BX_INSERTED)) {
259 // tell the device model that we removed, then inserted the disk
260 DEV_floppy_set_media_status(0, 0);
261 DEV_floppy_set_media_status(0, 1);
263 } else {
264 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set_enabled(!empty);
265 SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->set_enabled(!empty);
268 } else if (!strcmp(pname, BXPN_FLOPPYB_PATH)) {
269 if (set==1) {
270 if (SIM->get_init_done()) {
271 if (empty) {
272 DEV_floppy_set_media_status(1, 0);
273 bx_gui->update_drive_status_buttons();
274 } else {
275 if (!SIM->get_param_num(BXPN_FLOPPYB_TYPE)->get_enabled()) {
276 BX_ERROR(("Cannot add a floppy drive at runtime"));
277 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set("none");
280 if ((DEV_floppy_present()) &&
281 (SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->get() == BX_INSERTED)) {
282 // tell the device model that we removed, then inserted the disk
283 DEV_floppy_set_media_status(1, 0);
284 DEV_floppy_set_media_status(1, 1);
286 } else {
287 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set_enabled(!empty);
288 SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->set_enabled(!empty);
291 } else {
292 BX_PANIC(("bx_param_string_handler called with unknown parameter '%s'", pname));
295 return val;
298 static int bx_param_enable_handler (bx_param_c *param, int val)
300 char pname[BX_PATHNAME_LEN];
301 Bit8u channel, device;
303 bx_list_c *base = (bx_list_c*) param->get_parent();
304 base->get_param_path(pname, BX_PATHNAME_LEN);
305 if (!strncmp(pname, "ata.", 4)) {
306 channel = pname[4] - '0';
307 if (!strcmp(base->get_name(), "master")) {
308 device = 0;
309 } else {
310 device = 1;
312 if (!strcmp(param->get_name(), "status")) {
313 if (val != 0) {
314 switch (SIM->get_param_enum("type", base)->get()) {
315 case BX_ATA_DEVICE_CDROM:
316 return (1);
317 break;
320 } else if (!strcmp(param->get_name(), "journal")) {
321 if (val != 0) {
322 switch (SIM->get_param_enum("type", base)->get()) {
323 case BX_ATA_DEVICE_DISK:
324 switch (SIM->get_param_enum("mode", base)->get()) {
325 case BX_ATA_MODE_UNDOABLE:
326 case BX_ATA_MODE_VOLATILE:
327 // case BX_ATA_MODE_Z_UNDOABLE:
328 // case BX_ATA_MODE_Z_VOLATILE:
329 return (1);
330 break;
334 return (0);
335 } else {
336 BX_PANIC(("bx_param_enable_handler called with unknown parameter '%s'", pname));
338 } else {
339 BX_PANIC(("bx_param_enable_handler called with unknown parameter '%s'", pname));
341 return val;
344 void bx_init_options()
346 int i;
347 bx_list_c *menu;
348 bx_list_c *deplist;
349 bx_param_num_c *ioaddr, *ioaddr2, *irq;
350 bx_param_bool_c *enabled;
351 bx_param_enum_c *mode, *status, *type, *ethmod;
352 bx_param_string_c *macaddr, *ethdev;
353 bx_param_filename_c *path;
354 char name[BX_PATHNAME_LEN], descr[512], group[16], label[512];
356 bx_param_c *root_param = SIM->get_param(".");
358 // general options subtree
359 menu = new bx_list_c(root_param, "general", "");
361 // config interface option, set in bochsrc or command line
362 static const char *config_interface_list[] = {
363 #if BX_USE_TEXTCONFIG
364 "textconfig",
365 #endif
366 #if BX_WITH_WX
367 "wx",
368 #endif
369 NULL
371 bx_param_enum_c *sel_config = new bx_param_enum_c(menu,
372 "config_interface", "Configuration interface",
373 "Select configuration interface",
374 config_interface_list,
377 sel_config->set_by_name(BX_DEFAULT_CONFIG_INTERFACE);
379 // quick start option, set by command line arg
380 new bx_param_enum_c(menu,
381 "start_mode",
382 "Bochs start types",
383 "Bochs start types",
384 bochs_start_names,
385 BX_RUN_START,
386 BX_QUICK_START);
388 new bx_param_bool_c(menu,
389 "restore",
390 "Restore Bochs session",
391 "Restore Bochs session",
393 new bx_param_string_c(menu,
394 "restore_path",
395 "Path to data for restore",
396 "Path to data for restore",
398 BX_PATHNAME_LEN);
400 // benchmarking mode, set by command line arg
401 new bx_param_num_c(menu,
402 "benchmark",
403 "benchmark mode",
404 "set benchmark mode",
405 0, BX_MAX_BIT32U, 0);
407 // subtree for special menus
408 bx_list_c *special_menus = new bx_list_c(root_param, "menu", "");
410 #if BX_SUPPORT_SMP
411 #define BX_CPU_PROCESSORS_LIMIT 8
412 #define BX_CPU_CORES_LIMIT 4
413 #define BX_CPU_HT_THREADS_LIMIT 4
414 #else
415 #define BX_CPU_PROCESSORS_LIMIT 1
416 #define BX_CPU_CORES_LIMIT 1
417 #define BX_CPU_HT_THREADS_LIMIT 1
418 #endif
420 // cpu subtree
421 bx_list_c *cpu_param = new bx_list_c(root_param, "cpu", "CPU Options", 8 + BX_SUPPORT_SMP);
423 // cpu options
424 bx_param_num_c *nprocessors = new bx_param_num_c(cpu_param,
425 "n_processors", "Number of CPUs in SMP mode",
426 "Sets the number of CPUs for multiprocessor emulation",
427 1, BX_CPU_PROCESSORS_LIMIT,
429 nprocessors->set_enabled(BX_CPU_PROCESSORS_LIMIT > 1);
430 bx_param_num_c *ncores = new bx_param_num_c(cpu_param,
431 "n_cores", "Number of processor cores in each CPU in SMP mode",
432 "Sets the number of processor cores per CPU for multiprocessor emulation",
433 1, BX_CPU_CORES_LIMIT,
435 ncores->set_enabled(BX_CPU_CORES_LIMIT > 1);
436 bx_param_num_c *nthreads = new bx_param_num_c(cpu_param,
437 "n_threads", "Number of HT threads per each process core in SMP mode",
438 "Sets the number of HT (Intel(R) HyperThreading Technology) threads per core for multiprocessor emulation",
439 1, BX_CPU_HT_THREADS_LIMIT,
441 nthreads->set_enabled(BX_CPU_HT_THREADS_LIMIT > 1);
442 new bx_param_num_c(cpu_param,
443 "ips", "Emulated instructions per second (IPS)",
444 "Emulated instructions per second, used to calibrate bochs emulated time with wall clock time.",
445 1, BX_MAX_BIT32U,
446 2000000);
447 #if BX_SUPPORT_SMP
448 new bx_param_num_c(cpu_param,
449 "quantum", "Quantum ticks in SMP simulation",
450 "Maximum amount of instructions allowed to execute before returning control to another CPU.",
451 BX_SMP_QUANTUM_MIN, BX_SMP_QUANTUM_MAX,
453 #endif
454 new bx_param_bool_c(cpu_param,
455 "reset_on_triple_fault", "Enable CPU reset on triple fault",
456 "Enable CPU reset if triple fault occured (highly recommended)",
458 new bx_param_bool_c(cpu_param,
459 "cpuid_limit_winnt", "Limit max CPUID function to 3",
460 "Limit max CPUID function reported to 3 to workaround WinNT issue",
462 new bx_param_string_c(cpu_param,
463 "vendor_string",
464 "CPUID vendor string",
465 "Set the CPUID vendor string",
466 #if BX_CPU_VENDOR_INTEL
467 "GenuineIntel",
468 #else
469 "AuthenticAMD",
470 #endif
471 BX_CPUID_VENDOR_LEN+1);
472 new bx_param_string_c(cpu_param,
473 "brand_string",
474 "CPUID brand string",
475 "Set the CPUID brand string",
476 #if BX_CPU_VENDOR_INTEL
477 " Intel(R) Pentium(R) 4 CPU ",
478 #else
479 "AMD Athlon(tm) processor",
480 #endif
481 BX_CPUID_BRAND_LEN+1);
483 cpu_param->get_options()->set(menu->SHOW_PARENT);
485 // memory subtree
486 bx_list_c *memory = new bx_list_c(root_param, "memory", "Memory Options");
487 bx_list_c *stdmem = new bx_list_c(memory, "standard", "Standard Options");
488 bx_list_c *optrom = new bx_list_c(memory, "optrom", "Optional ROM Images");
489 bx_list_c *optram = new bx_list_c(memory, "optram", "Optional RAM Images");
490 bx_list_c *ram = new bx_list_c(stdmem, "ram", "");
491 bx_list_c *rom = new bx_list_c(stdmem, "rom", "");
492 bx_list_c *vgarom = new bx_list_c(stdmem, "vgarom", "");
494 // memory options (ram & rom)
495 bx_param_num_c *ramsize = new bx_param_num_c(ram,
496 "size",
497 "Memory size (megabytes)",
498 "Amount of RAM in megabytes",
499 1, 2048,
500 BX_DEFAULT_MEM_MEGS);
501 ramsize->set_ask_format("Enter memory size (MB): [%d] ");
502 #if BX_WITH_WX
503 ramsize->set_options(bx_param_num_c::USE_SPIN_CONTROL);
504 #endif
506 path = new bx_param_filename_c(rom,
507 "path",
508 "ROM BIOS image",
509 "Pathname of ROM image to load",
510 "", BX_PATHNAME_LEN);
511 path->set_format("Name of ROM BIOS image: %s");
512 sprintf(name, "%s/BIOS-bochs-latest", (char *)get_builtin_variable("BXSHARE"));
513 path->set_initial_val(name);
514 bx_param_num_c *romaddr = new bx_param_num_c(rom,
515 "addr",
516 "ROM BIOS address",
517 "The address at which the ROM image should be loaded",
518 0, BX_MAX_BIT32U,
520 romaddr->set_base(16);
521 romaddr->set_format("0x%05x");
522 romaddr->set_long_format("ROM BIOS address: 0x%05x");
524 path = new bx_param_filename_c(vgarom,
525 "path",
526 "VGA BIOS image",
527 "Pathname of VGA ROM image to load",
528 "", BX_PATHNAME_LEN);
529 path->set_format("Name of VGA BIOS image: %s");
530 sprintf(name, "%s/VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE"));
531 path->set_initial_val(name);
533 bx_param_num_c *optaddr;
535 for (i=0; i<BX_N_OPTROM_IMAGES; i++) {
536 sprintf(name, "%d", i+1);
537 sprintf(descr, "Pathname of optional ROM image #%d to load", i+1);
538 sprintf(label, "Optional ROM image #%d", i+1);
539 bx_list_c *optnum1 = new bx_list_c(optrom, name, label);
540 path = new bx_param_filename_c(optnum1,
541 "path",
542 "Path",
543 descr,
544 "", BX_PATHNAME_LEN);
545 sprintf(label, "Name of optional ROM image #%d", i+1);
546 strcat(label, " : %s");
547 path->set_format(strdup(label));
548 sprintf(descr, "The address at which the optional ROM image #%d should be loaded", i+1);
549 optaddr = new bx_param_num_c(optnum1,
550 "addr",
551 "Address",
552 descr,
553 0, BX_MAX_BIT32U,
555 optaddr->set_base(16);
556 optaddr->set_format("0x%05x");
557 sprintf(label, "Optional ROM #%d address:", i+1);
558 strcat(label, " 0x%05x");
559 optaddr->set_long_format(strdup(label));
560 optnum1->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
562 optrom->get_options()->set(bx_list_c::SHOW_PARENT);
564 for (i=0; i<BX_N_OPTRAM_IMAGES; i++) {
565 sprintf(name, "%d", i+1);
566 sprintf(descr, "Pathname of optional RAM image #%d to load", i+1);
567 sprintf(label, "Optional RAM image #%d", i+1);
568 bx_list_c *optnum2 = new bx_list_c(optram, name, label);
569 path = new bx_param_filename_c(optnum2,
570 "path",
571 "Path",
572 descr,
573 "", BX_PATHNAME_LEN);
574 sprintf(label, "Name of optional RAM image #%d", i+1);
575 strcat(label, " : %s");
576 path->set_format(strdup(label));
577 sprintf(descr, "The address at which the optional RAM image #%d should be loaded", i+1);
578 optaddr = new bx_param_num_c(optnum2,
579 "addr",
580 "Address",
581 descr,
582 0, BX_MAX_BIT32U,
584 optaddr->set_base(16);
585 optaddr->set_format("0x%05x");
586 sprintf(label, "Optional RAM #%d address:", i+1);
587 strcat(label, " 0x%05x");
588 optaddr->set_long_format(strdup(label));
589 optnum2->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
591 optrom->get_options()->set(bx_list_c::SHOW_PARENT);
592 memory->get_options()->set(bx_list_c::USE_TAB_WINDOW);
594 bx_param_c *memory_init_list[] = {
595 SIM->get_param(BXPN_MEM_SIZE),
596 SIM->get_param(BXPN_ROM_PATH),
597 SIM->get_param(BXPN_ROM_ADDRESS),
598 SIM->get_param(BXPN_VGA_ROM_PATH),
599 SIM->get_param("memory.optrom"),
600 SIM->get_param("memory.optram"),
601 NULL
603 menu = new bx_list_c(special_menus, "memory", "Bochs Memory Options", memory_init_list);
604 menu->get_options()->set(bx_list_c::SHOW_PARENT);
606 // clock & cmos subtree
607 bx_list_c *clock_cmos = new bx_list_c(root_param, "clock_cmos", "Clock & CMOS Options");
609 // clock & cmos options
610 bx_param_enum_c *clock_sync = new bx_param_enum_c(clock_cmos,
611 "clock_sync", "Synchronisation method",
612 "Host to guest time synchronization method",
613 clock_sync_names,
614 BX_CLOCK_SYNC_NONE,
615 BX_CLOCK_SYNC_NONE);
616 bx_param_num_c *time0 = new bx_param_num_c(clock_cmos,
617 "time0",
618 "Initial CMOS time for Bochs\n(1:localtime, 2:utc, other:time in seconds)",
619 "Initial time for Bochs CMOS clock, used if you really want two runs to be identical",
620 0, BX_MAX_BIT32U,
621 BX_CLOCK_TIME0_LOCAL);
623 bx_list_c *cmosimage = new bx_list_c(clock_cmos, "cmosimage", "CMOS Image Options");
624 bx_param_bool_c *use_cmosimage = new bx_param_bool_c(cmosimage,
625 "enabled", "Use a CMOS image",
626 "Controls the usage of a CMOS image",
628 path = new bx_param_filename_c(cmosimage,
629 "path", "Pathname of CMOS image",
630 "Pathname of CMOS image",
631 "", BX_PATHNAME_LEN);
632 bx_param_bool_c *rtc_init = new bx_param_bool_c(cmosimage,
633 "rtc_init", "Initialize RTC from image",
634 "Controls whether to initialize the RTC with values stored in the image",
636 deplist = new bx_list_c(NULL, 2);
637 deplist->add(path);
638 deplist->add(rtc_init);
639 use_cmosimage->set_dependent_list(deplist);
641 time0->set_ask_format("Enter Initial CMOS time (1:localtime, 2:utc, other:time in seconds): [%d] ");
642 clock_sync->set_ask_format("Enter Synchronisation method: [%s] ");
643 clock_cmos->get_options()->set(bx_list_c::SHOW_PARENT);
644 cmosimage->get_options()->set(bx_list_c::SHOW_PARENT);
646 // pci subtree
647 bx_list_c *pci = new bx_list_c(root_param, "pci", "PCI Options");
649 // pci options
650 bx_param_c *pci_deps_list[3+BX_N_PCI_SLOTS+2*BX_SUPPORT_PCIDEV];
651 bx_param_c **pci_deps_ptr = &pci_deps_list[0];
653 bx_param_bool_c *i440fx_support = new bx_param_bool_c(pci,
654 "i440fx_support",
655 "Enable i440FX PCI Support",
656 "Controls whether to emulate the i440FX PCI chipset",
657 BX_SUPPORT_PCI);
658 // pci slots
659 bx_list_c *slot = new bx_list_c(pci, "slot", "PCI Slots");
660 *pci_deps_ptr++ = slot;
661 for (i=0; i<BX_N_PCI_SLOTS; i++) {
662 sprintf(name, "%d", i+1);
663 sprintf (descr, "Name of the device connected to PCI slot #%d", i+1);
664 sprintf (label, "PCI slot #%d device", i+1);
665 bx_param_string_c *devname = new bx_param_string_c(slot,
666 name,
667 label,
668 descr,
669 "", BX_PATHNAME_LEN);
670 // add to deplist
671 *pci_deps_ptr++ = devname;
673 // pcidev options
674 bx_list_c *pcidev = new bx_list_c(pci, "pcidev", "Host PCI Device Mapping");
675 *pci_deps_ptr++ = pcidev;
676 bx_param_num_c *pcivid = new bx_param_num_c(pcidev,
677 "vendor",
678 "PCI Vendor ID",
679 "The vendor ID of the host PCI device to map",
680 0, 0xffff,
681 0xffff); // vendor id 0xffff = no pci device present
682 pcivid->set_base(16);
683 pcivid->set_format("0x%04x");
684 pcivid->set_long_format("PCI Vendor ID: 0x%04x");
685 #if BX_SUPPORT_PCIDEV
686 *pci_deps_ptr++ = pcivid;
687 #else
688 pcivid->set_enabled(0);
689 #endif
690 bx_param_num_c *pcidid = new bx_param_num_c(pcidev,
691 "device",
692 "PCI Device ID",
693 "The device ID of the host PCI device to map",
694 0, 0xffff,
695 0x0);
696 pcidid->set_base(16);
697 pcidid->set_format("0x%04x");
698 pcidid->set_long_format("PCI Device ID: 0x%04x");
699 #if BX_SUPPORT_PCIDEV
700 *pci_deps_ptr++ = pcidid;
701 #else
702 pcidid->set_enabled(0);
703 #endif
704 // add final NULL at the end, and build the menu
705 *pci_deps_ptr = NULL;
706 i440fx_support->set_dependent_list(new bx_list_c(NULL, "", "", pci_deps_list));
707 pci->get_options()->set(bx_list_c::SHOW_PARENT);
708 slot->get_options()->set(bx_list_c::SHOW_PARENT);
709 pcidev->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
711 // display subtree
712 bx_list_c *display = new bx_list_c(root_param, "display", "Bochs Display & Interface Options", 7);
714 // this is a list of gui libraries that are known to be available at
715 // compile time. The one that is listed first will be the default,
716 // which is used unless the user overrides it on the command line or
717 // in a configuration file.
718 static const char *display_library_list[] = {
719 #if BX_WITH_X11
720 "x",
721 #endif
722 #if BX_WITH_WIN32
723 "win32",
724 #endif
725 #if BX_WITH_CARBON
726 "carbon",
727 #endif
728 #if BX_WITH_BEOS
729 "beos",
730 #endif
731 #if BX_WITH_MACOS
732 "macos",
733 #endif
734 #if BX_WITH_AMIGAOS
735 "amigaos",
736 #endif
737 #if BX_WITH_SDL
738 "sdl",
739 #endif
740 #if BX_WITH_SVGA
741 "svga",
742 #endif
743 #if BX_WITH_TERM
744 "term",
745 #endif
746 #if BX_WITH_RFB
747 "rfb",
748 #endif
749 #if BX_WITH_WX
750 "wx",
751 #endif
752 #if BX_WITH_NOGUI
753 "nogui",
754 #endif
755 NULL
757 bx_param_enum_c *sel_displaylib = new bx_param_enum_c(display,
758 "display_library", "VGA Display Library",
759 "Select VGA Display Library",
760 display_library_list,
763 sel_displaylib->set_by_name(BX_DEFAULT_DISPLAY_LIBRARY);
764 sel_displaylib->set_ask_format("Choose which library to use for the Bochs display: [%s] ");
766 new bx_param_string_c(display,
767 "displaylib_options", "Display Library options",
768 "Options passed to Display Library",
770 BX_PATHNAME_LEN);
772 new bx_param_bool_c(display,
773 "private_colormap", "Use a private colormap",
774 "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.",
777 bx_param_bool_c *fullscreen = new bx_param_bool_c(display,
778 "fullscreen", "Use full screen mode",
779 "When enabled, bochs occupies the whole screen instead of just a window.",
781 bx_param_string_c *screenmode = new bx_param_string_c(display,
782 "screenmode",
783 "Screen mode name",
784 "Screen mode name",
785 "", BX_PATHNAME_LEN);
786 screenmode->set_handler(bx_param_string_handler);
787 #if !BX_WITH_AMIGAOS
788 fullscreen->set_enabled(0);
789 screenmode->set_enabled(0);
790 #endif
792 bx_param_num_c *vga_update_interval = new bx_param_num_c(display,
793 "vga_update_interval",
794 "VGA Update Interval",
795 "Number of microseconds between VGA updates",
796 1, BX_MAX_BIT32U,
797 40000);
798 vga_update_interval->set_ask_format ("Type a new value for VGA update interval: [%d] ");
800 bx_param_string_c *vga_extension = new bx_param_string_c(display,
801 "vga_extension",
802 "VGA Extension",
803 "Name of the VGA extension",
804 "none", BX_PATHNAME_LEN);
805 #if BX_SUPPORT_VBE
806 vga_extension->set_initial_val("vbe");
807 #elif BX_SUPPORT_CLGD54XX
808 vga_extension->set_initial_val("cirrus");
809 #endif
810 display->get_options()->set(bx_list_c::SHOW_PARENT);
812 // keyboard & mouse subtree
813 bx_list_c *kbd_mouse = new bx_list_c(root_param, "keyboard_mouse", "Keyboard & Mouse Options");
814 bx_list_c *keyboard = new bx_list_c(kbd_mouse, "keyboard", "Keyboard Options");
815 bx_list_c *mouse = new bx_list_c(kbd_mouse, "mouse", "Mouse Options");
817 // keyboard & mouse options
818 type = new bx_param_enum_c(keyboard,
819 "type", "Keyboard type",
820 "Keyboard type reported by the 'identify keyboard' command",
821 keyboard_type_names,
822 BX_KBD_MF_TYPE,
823 BX_KBD_XT_TYPE);
824 type->set_ask_format ("Enter keyboard type: [%s] ");
826 new bx_param_num_c(keyboard,
827 "serial_delay", "Keyboard serial delay",
828 "Approximate time in microseconds that it takes one character to be transfered from the keyboard to controller over the serial path.",
829 1, BX_MAX_BIT32U,
830 250);
831 new bx_param_num_c(keyboard,
832 "paste_delay", "Keyboard paste delay",
833 "Approximate time in microseconds between attemps to paste characters to the keyboard controller.",
834 1000, BX_MAX_BIT32U,
835 100000);
836 bx_param_bool_c *use_kbd_mapping = new bx_param_bool_c(keyboard,
837 "use_mapping", "Use keyboard mapping",
838 "Controls whether to use the keyboard mapping feature",
840 bx_param_filename_c *keymap = new bx_param_filename_c(keyboard,
841 "keymap", "Keymap filename",
842 "Pathname of the keymap file used",
843 "", BX_PATHNAME_LEN);
844 deplist = new bx_list_c(NULL, 1);
845 deplist->add(keymap);
846 use_kbd_mapping->set_dependent_list(deplist);
848 bx_param_string_c *user_shortcut = new bx_param_string_c(keyboard,
849 "user_shortcut",
850 "Userbutton shortcut",
851 "Defines the keyboard shortcut to be sent when you press the 'user' button in the headerbar.",
852 "none", 20);
853 user_shortcut->set_runtime_param(1);
855 static const char *mouse_type_list[] = {
856 "none",
857 "ps2",
858 "imps2",
859 #if BX_SUPPORT_BUSMOUSE
860 "bus",
861 #endif
862 "serial",
863 "serial_wheel",
864 "serial_msys",
865 NULL
867 type = new bx_param_enum_c(mouse,
868 "type", "Mouse type",
869 "The mouse type can be one of these: 'none', 'ps2', 'imps2', 'serial', 'serial_wheel'"
870 #if BX_SUPPORT_BUSMOUSE
871 ", 'bus'"
872 #endif
874 mouse_type_list,
875 BX_MOUSE_TYPE_PS2,
876 BX_MOUSE_TYPE_NONE);
877 type->set_ask_format("Choose the type of mouse [%s] ");
879 new bx_param_bool_c(mouse,
880 "enabled", "Enable the mouse capture",
881 "Controls whether the mouse sends events to the guest. The hardware emulation is always enabled.",
883 kbd_mouse->get_options()->set(bx_list_c::SHOW_PARENT);
884 keyboard->get_options()->set(bx_list_c::SHOW_PARENT);
885 mouse->get_options()->set(bx_list_c::SHOW_PARENT);
887 // boot parameter subtree
888 bx_list_c *boot_params = new bx_list_c(root_param, "boot_params", "Boot Options");
889 // boot sequence
890 for (i=0; i<3; i++) {
891 sprintf(name, "boot_drive%d", i+1);
892 sprintf(label, "Boot drive #%d", i+1);
893 sprintf(descr, "Name of drive #%d in boot sequence (A, C or CD)", i+1);
894 bx_param_enum_c *bootdrive = new bx_param_enum_c(boot_params,
895 name,
896 label,
897 descr,
898 &bochs_bootdisk_names[(i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE],
899 (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE,
900 (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE);
901 bootdrive->set_ask_format("Boot from floppy drive, hard drive or cdrom ? [%s] ");
904 new bx_param_bool_c(boot_params,
905 "floppy_sig_check",
906 "Skip Floppy Boot Signature Check",
907 "Skips check for the 0xaa55 signature on floppy boot device.",
910 // loader hack
911 bx_list_c *load32bitos = new bx_list_c(boot_params, "load32bitos", "32-bit OS Loader Hack");
912 bx_param_enum_c *whichOS = new bx_param_enum_c(load32bitos,
913 "which",
914 "Which operating system?",
915 "Which OS to boot",
916 loader_os_names,
917 Load32bitOSNone,
918 Load32bitOSNone);
919 path = new bx_param_filename_c(load32bitos,
920 "path",
921 "Pathname of OS to load",
922 "Pathname of the 32-bit OS to load",
923 "", BX_PATHNAME_LEN);
924 bx_param_filename_c *iolog = new bx_param_filename_c(load32bitos,
925 "iolog",
926 "Pathname of I/O log file",
927 "I/O logfile used for initializing the hardware",
928 "", BX_PATHNAME_LEN);
929 bx_param_filename_c *initrd = new bx_param_filename_c(load32bitos,
930 "initrd",
931 "Pathname of initrd",
932 "Pathname of the initial ramdisk",
933 "", BX_PATHNAME_LEN);
934 whichOS->set_ask_format("Enter OS to load: [%s] ");
935 path->set_ask_format("Enter pathname of OS: [%s]");
936 iolog->set_ask_format("Enter pathname of I/O log: [%s] ");
937 initrd->set_ask_format("Enter pathname of initrd: [%s] ");
938 load32bitos->get_options()->set(menu->SERIES_ASK);
939 whichOS->set_handler(bx_param_handler);
940 whichOS->set(Load32bitOSNone);
941 boot_params->get_options()->set(bx_list_c::SHOW_PARENT);
943 // floppy subtree
944 bx_list_c *floppy = new bx_list_c(root_param, "floppy", "Floppy Options");
945 bx_list_c *floppya = new bx_list_c(floppy, "0", "Floppy Disk 0");
946 bx_list_c *floppyb = new bx_list_c(floppy, "1", "Floppy Disk 1");
948 bx_param_enum_c *devtype;
949 // floppy options
950 path = new bx_param_filename_c(floppya,
951 "path",
952 "First floppy image/device",
953 "Pathname of first floppy image file or device. If you're booting from floppy, this should be a bootable floppy.",
954 "", BX_PATHNAME_LEN);
955 path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] ");
956 path->set_runtime_param(1);
958 devtype = new bx_param_enum_c(floppya,
959 "devtype",
960 "Type of floppy drive",
961 "Type of floppy drive",
962 floppy_type_names,
963 BX_FLOPPY_NONE,
964 BX_FLOPPY_NONE);
965 devtype->set_enabled(0); // hide devtype parameter
966 type = new bx_param_enum_c(floppya,
967 "type",
968 "Type of floppy disk",
969 "Type of floppy disk",
970 floppy_type_names,
971 BX_FLOPPY_NONE,
972 BX_FLOPPY_NONE);
973 type->set_ask_format("What type of floppy disk? (auto=detect) [%s] ");
974 type->set_runtime_param(1);
976 status = new bx_param_enum_c(floppya,
977 "status",
978 "Is floppya inserted",
979 "Inserted or ejected",
980 floppy_status_names,
981 BX_INSERTED,
982 BX_EJECTED);
983 status->set_ask_format("Is the floppy inserted or ejected? [%s] ");
984 status->set_runtime_param(1);
986 path->set_handler(bx_param_string_handler);
987 type->set_handler(bx_param_handler);
988 status->set_handler(bx_param_handler);
989 path->set_initial_val("none");
990 floppya->get_options()->set(bx_list_c::SERIES_ASK);
992 path = new bx_param_filename_c(floppyb,
993 "path",
994 "Second floppy image/device",
995 "Pathname of second floppy image file or device.",
996 "", BX_PATHNAME_LEN);
997 path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] ");
998 path->set_runtime_param(1);
1000 devtype = new bx_param_enum_c(floppyb,
1001 "devtype",
1002 "Type of floppy drive",
1003 "Type of floppy drive",
1004 floppy_type_names,
1005 BX_FLOPPY_NONE,
1006 BX_FLOPPY_NONE);
1007 devtype->set_enabled(0); // hide devtype parameter
1008 type = new bx_param_enum_c(floppyb,
1009 "type",
1010 "Type of floppy disk",
1011 "Type of floppy disk",
1012 floppy_type_names,
1013 BX_FLOPPY_NONE,
1014 BX_FLOPPY_NONE);
1015 type->set_ask_format("What type of floppy disk? (auto=detect) [%s] ");
1016 type->set_runtime_param(1);
1018 status = new bx_param_enum_c(floppyb,
1019 "status",
1020 "Is floppyb inserted",
1021 "Inserted or ejected",
1022 floppy_status_names,
1023 BX_INSERTED,
1024 BX_EJECTED);
1025 status->set_ask_format("Is the floppy inserted or ejected? [%s] ");
1026 status->set_runtime_param(1);
1028 path->set_handler(bx_param_string_handler);
1029 type->set_handler(bx_param_handler);
1030 status->set_handler(bx_param_handler);
1031 path->set_initial_val("none");
1032 floppyb->get_options()->set(bx_list_c::SERIES_ASK);
1033 floppy->get_options()->set(bx_list_c::SHOW_PARENT);
1035 // ATA/ATAPI subtree
1036 bx_list_c *ata = new bx_list_c(root_param, "ata", "ATA/ATAPI Options");
1038 // disk options
1039 const char *s_atachannel[] = {
1040 "ATA channel 0",
1041 "ATA channel 1",
1042 "ATA channel 2",
1043 "ATA channel 3",
1045 const char *s_atadevname[2] = {
1046 "master",
1047 "slave",
1049 const char *s_atadevice[4][2] = {
1050 { "First HD/CD on channel 0",
1051 "Second HD/CD on channel 0" },
1052 { "First HD/CD on channel 1",
1053 "Second HD/CD on channel 1" },
1054 { "First HD/CD on channel 2",
1055 "Second HD/CD on channel 2" },
1056 { "First HD/CD on channel 3",
1057 "Second HD/CD on channel 3" }
1059 Bit16u ata_default_ioaddr1[4] = {
1060 0x1f0, 0x170, 0x1e8, 0x168
1062 Bit16u ata_default_ioaddr2[4] = {
1063 0x3f0, 0x370, 0x3e0, 0x360
1065 Bit8u ata_default_irq[4] = {
1066 14, 15, 11, 9
1069 #define BXP_PARAMS_PER_ATA_DEVICE 12
1071 bx_list_c *ata_menu[BX_MAX_ATA_CHANNEL];
1072 bx_list_c *ata_res[BX_MAX_ATA_CHANNEL];
1074 Bit8u channel;
1075 for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
1077 sprintf(name, "%d", channel);
1078 ata_menu[channel] = new bx_list_c(ata, name, s_atachannel[channel]);
1079 ata_menu[channel]->get_options()->set(bx_list_c::USE_TAB_WINDOW);
1080 ata_res[channel] = new bx_list_c(ata_menu[channel], "resources", s_atachannel[channel], 8);
1081 ata_res[channel]->get_options()->set(bx_list_c::SERIES_ASK);
1083 enabled = new bx_param_bool_c(ata_res[channel],
1084 "enabled",
1085 "Enable ATA channel",
1086 "Controls whether ata channel is installed or not",
1088 enabled->set_ask_format("Channel is enabled: [%s] ");
1090 ioaddr = new bx_param_num_c(ata_res[channel],
1091 "ioaddr1",
1092 "I/O Address 1",
1093 "IO adress of ata command block",
1094 0, 0xffff,
1095 ata_default_ioaddr1[channel]);
1096 ioaddr->set_base(16);
1097 ioaddr->set_ask_format("Enter new ioaddr1: [0x%x] ");
1099 ioaddr2 = new bx_param_num_c(ata_res[channel],
1100 "ioaddr2",
1101 "I/O Address 2",
1102 "IO adress of ata control block",
1103 0, 0xffff,
1104 ata_default_ioaddr2[channel]);
1105 ioaddr2->set_base(16);
1106 ioaddr2->set_ask_format("Enter new ioaddr2: [0x%x] ");
1108 irq = new bx_param_num_c(ata_res[channel],
1109 "irq",
1110 "IRQ",
1111 "IRQ used by this ata channel",
1112 0, 15,
1113 ata_default_irq[channel]);
1114 irq->set_ask_format("Enter new IRQ: [%d] ");
1115 irq->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1117 // all items in the ata[channel] menu depend on the enabled flag.
1118 // The menu list is complete, but a few dependent_list items will
1119 // be added later. Use clone() to make a copy of the dependent_list
1120 // so that it can be changed without affecting the menu.
1121 enabled->set_dependent_list(ata_res[channel]->clone());
1123 for (Bit8u slave=0; slave<2; slave++) {
1124 menu = new bx_list_c(ata_menu[channel],
1125 s_atadevname[slave],
1126 s_atadevice[channel][slave],
1127 BXP_PARAMS_PER_ATA_DEVICE + 1);
1128 menu->get_options()->set(bx_list_c::SERIES_ASK);
1130 bx_param_bool_c *present = new bx_param_bool_c(menu,
1131 "present",
1132 "Enable this device",
1133 "Controls whether ata device is installed or not",
1135 present->set_ask_format("Device is enabled: [%s] ");
1137 type = new bx_param_enum_c(menu,
1138 "type",
1139 "Type of ATA device",
1140 "Type of ATA device (disk or cdrom)",
1141 atadevice_type_names,
1142 BX_ATA_DEVICE_DISK,
1143 BX_ATA_DEVICE_DISK);
1144 type->set_ask_format("Enter type of ATA device, disk or cdrom: [%s] ");
1146 path = new bx_param_filename_c(menu,
1147 "path",
1148 "Path or physical device name",
1149 "Pathname of the image or physical device (cdrom only)",
1150 "", BX_PATHNAME_LEN);
1151 path->set_ask_format("Enter new filename: [%s] ");
1153 mode = new bx_param_enum_c(menu,
1154 "mode",
1155 "Type of disk image",
1156 "Mode of the ATA harddisk",
1157 atadevice_mode_names,
1158 BX_ATA_MODE_FLAT,
1159 BX_ATA_MODE_FLAT);
1160 mode->set_ask_format("Enter mode of ATA device, (flat, concat, etc.): [%s] ");
1162 status = new bx_param_enum_c(menu,
1163 "status",
1164 "Inserted",
1165 "CD-ROM media status (inserted / ejected)",
1166 atadevice_status_names,
1167 BX_INSERTED,
1168 BX_EJECTED);
1169 status->set_ask_format("Is the device inserted or ejected? [%s] ");
1171 bx_param_filename_c *journal = new bx_param_filename_c(menu,
1172 "journal",
1173 "Path of journal file",
1174 "Pathname of the journal file",
1175 "", BX_PATHNAME_LEN);
1176 journal->set_ask_format("Enter path of journal file: [%s]");
1178 bx_param_num_c *cylinders = new bx_param_num_c(menu,
1179 "cylinders",
1180 "Cylinders",
1181 "Number of cylinders",
1182 0, 262143,
1184 cylinders->set_ask_format("Enter number of cylinders: [%d] ");
1185 bx_param_num_c *heads = new bx_param_num_c(menu,
1186 "heads",
1187 "Heads",
1188 "Number of heads",
1189 0, 255,
1191 heads->set_ask_format("Enter number of heads: [%d] ");
1192 bx_param_num_c *spt = new bx_param_num_c(menu,
1193 "spt",
1194 "Sectors per track",
1195 "Number of sectors per track",
1196 0, 255,
1198 spt->set_ask_format("Enter number of sectors per track: [%d] ");
1200 bx_param_string_c *model = new bx_param_string_c(menu,
1201 "model",
1202 "Model name",
1203 "String returned by the 'identify device' command",
1204 "Generic 1234", 41);
1205 model->set_ask_format("Enter new model name: [%s]");
1207 bx_param_enum_c *biosdetect = new bx_param_enum_c(menu,
1208 "biosdetect",
1209 "BIOS Detection",
1210 "Type of bios detection",
1211 atadevice_biosdetect_names,
1212 BX_ATA_BIOSDETECT_AUTO,
1213 BX_ATA_BIOSDETECT_NONE);
1214 biosdetect->set_ask_format("Enter bios detection type: [%s]");
1216 bx_param_enum_c *translation = new bx_param_enum_c(menu,
1217 "translation",
1218 "Translation type",
1219 "How the ata-disk translation is done by the bios",
1220 atadevice_translation_names,
1221 BX_ATA_TRANSLATION_AUTO,
1222 BX_ATA_TRANSLATION_NONE);
1223 translation->set_ask_format("Enter translation type: [%s]");
1225 // the menu and all items on it depend on the present flag
1226 present->set_dependent_list(menu->clone());
1227 // the present flag depends on the ATA channel's enabled flag
1228 enabled->get_dependent_list()->add(present);
1229 // the master/slave menu depends on the ATA channel's enabled flag
1230 enabled->get_dependent_list()->add(menu);
1232 type->set_handler(bx_param_handler);
1233 mode->set_handler(bx_param_handler);
1234 status->set_handler(bx_param_handler);
1235 path->set_handler(bx_param_string_handler);
1237 // Set the enable_hanlders
1238 journal->set_enable_handler(bx_param_enable_handler);
1239 status->set_enable_handler(bx_param_enable_handler);
1242 // Enable two ATA interfaces by default, disable the others.
1243 // Now that the dependence relationships are established, call set() on
1244 // the ata device present params to set all enables correctly.
1245 enabled->set_initial_val(channel<2);
1246 enabled->set(channel<2);
1249 // disk menu
1250 bx_param_c *disk_menu_init_list[] = {
1251 SIM->get_param(BXPN_FLOPPYA),
1252 SIM->get_param(BXPN_FLOPPYB),
1253 SIM->get_param(BXPN_ATA0_RES),
1254 SIM->get_param(BXPN_ATA0_MASTER),
1255 SIM->get_param(BXPN_ATA0_SLAVE),
1256 #if BX_MAX_ATA_CHANNEL>1
1257 SIM->get_param(BXPN_ATA1_RES),
1258 SIM->get_param(BXPN_ATA1_MASTER),
1259 SIM->get_param(BXPN_ATA1_SLAVE),
1260 #endif
1261 #if BX_MAX_ATA_CHANNEL>2
1262 SIM->get_param(BXPN_ATA2_RES),
1263 SIM->get_param(BXPN_ATA2_MASTER),
1264 SIM->get_param(BXPN_ATA2_SLAVE),
1265 #endif
1266 #if BX_MAX_ATA_CHANNEL>3
1267 SIM->get_param(BXPN_ATA3_RES),
1268 SIM->get_param(BXPN_ATA3_MASTER),
1269 SIM->get_param(BXPN_ATA3_SLAVE),
1270 #endif
1271 SIM->get_param("boot_params"),
1272 NULL
1274 menu = new bx_list_c(special_menus, "disk", "Bochs Disk Options", disk_menu_init_list);
1275 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1277 // ports subtree
1278 bx_list_c *ports = new bx_list_c(root_param, "ports", "Serial and Parallel Port Options");
1279 ports->get_options()->set(bx_list_c::USE_TAB_WINDOW | bx_list_c::SHOW_PARENT);
1281 // parallel ports
1282 bx_list_c *parallel = new bx_list_c(ports, "parallel", "Parallel Port Options");
1283 parallel->get_options()->set(bx_list_c::SHOW_PARENT);
1284 for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
1285 sprintf(name, "%d", i+1);
1286 sprintf(label, "Parallel Port %d", i+1);
1287 menu = new bx_list_c(parallel, name, label);
1288 menu->get_options()->set(bx_list_c::SERIES_ASK);
1289 sprintf(label, "Enable parallel port #%d", i+1);
1290 sprintf(descr, "Controls whether parallel port #%d is installed or not", i+1);
1291 enabled = new bx_param_bool_c(menu, "enabled", label, descr,
1292 (i==0)? 1 : 0); // only enable #1 by default
1293 sprintf(label, "Parallel port #%d output file", i+1);
1294 sprintf(descr, "Data written to parport#%d by the guest OS is written to this file", i+1);
1295 path = new bx_param_filename_c(menu, "outfile", label, descr,
1296 "", BX_PATHNAME_LEN);
1297 deplist = new bx_list_c(NULL, 1);
1298 deplist->add(path);
1299 enabled->set_dependent_list(deplist);
1302 static const char *serial_mode_list[] = {
1303 "null",
1304 "file",
1305 "pipe",
1306 "pipe-client",
1307 "pipe-server",
1308 "term",
1309 "raw",
1310 "mouse",
1311 "socket",
1312 "socket-client",
1313 "socket-server",
1314 NULL
1317 // serial ports
1318 bx_list_c *serial = new bx_list_c(ports, "serial", "Serial Port Options");
1319 serial->get_options()->set(bx_list_c::SHOW_PARENT);
1320 for (i=0; i<BX_N_SERIAL_PORTS; i++) {
1321 sprintf(name, "%d", i+1);
1322 sprintf(label, "Serial Port %d", i+1);
1323 menu = new bx_list_c(serial, name, label);
1324 menu->get_options()->set(bx_list_c::SERIES_ASK);
1325 sprintf(label, "Enable serial port #%d (COM%d)", i+1, i+1);
1326 sprintf(descr, "Controls whether COM%d is installed or not", i+1);
1327 enabled = new bx_param_bool_c(menu, "enabled", label, descr,
1328 (i==0)?1 : 0); // only enable the first by default
1329 sprintf(label, "I/O mode of the serial device for COM%d", i+1);
1330 sprintf(descr, "The mode can be one these: 'null', 'file', 'pipe', 'term', 'raw', 'mouse', 'socket'");
1331 mode = new bx_param_enum_c(menu, "mode", label, descr,
1332 serial_mode_list, 0, 0);
1333 mode->set_ask_format("Choose I/O mode of the serial device [%s] ");
1334 sprintf(label, "Pathname of the serial device for COM%d", i+1);
1335 sprintf(descr, "The path can be a real serial device or a pty (X/Unix only)");
1336 path = new bx_param_filename_c(menu, "dev", label, descr,
1337 "", BX_PATHNAME_LEN);
1338 deplist = new bx_list_c(NULL, 2);
1339 deplist->add(mode);
1340 deplist->add(path);
1341 enabled->set_dependent_list(deplist);
1344 bx_param_string_c *port;
1346 // usb hubs
1347 bx_list_c *usb = new bx_list_c(ports, "usb", "USB Hub Options");
1348 usb->get_options()->set(bx_list_c::SHOW_PARENT);
1349 for (i=0; i<BX_N_USB_HUBS; i++) {
1350 sprintf(group, "USB%d", i+1);
1351 sprintf(name, "%d", i+1);
1352 sprintf(label, "USB Hub %d", i+1);
1353 menu = new bx_list_c(usb, name, label);
1354 menu->set_enabled(BX_SUPPORT_PCIUSB);
1355 sprintf(label, "Enable usb hub #%d", i+1);
1356 sprintf(descr, "Controls whether %s is installed or not", group);
1357 enabled = new bx_param_bool_c(menu, "enabled", label, descr, 0);
1358 enabled->set_enabled(BX_SUPPORT_PCIUSB);
1359 port = new bx_param_string_c(menu,
1360 "port1",
1361 "Port #1 device",
1362 "Device connected to USB port #1",
1363 "", BX_PATHNAME_LEN);
1364 port->set_group(group);
1365 port = new bx_param_string_c(menu,
1366 "port2",
1367 "Port #2 device",
1368 "Device connected to USB port #2",
1369 "", BX_PATHNAME_LEN);
1370 port->set_group(group);
1371 enabled->set_dependent_list(menu->clone());
1374 // network subtree
1375 bx_list_c *network = new bx_list_c(root_param, "network", "Network Configuration");
1376 network->get_options()->set(bx_list_c::USE_TAB_WINDOW | bx_list_c::SHOW_PARENT);
1378 // ne2k & pnic options
1379 static const char *eth_module_list[] = {
1380 "null",
1381 #if defined(ETH_LINUX)
1382 "linux",
1383 #endif
1384 #if HAVE_ETHERTAP
1385 "tap",
1386 #endif
1387 #if HAVE_TUNTAP
1388 "tuntap",
1389 #endif
1390 #if defined(ETH_WIN32)
1391 "win32",
1392 #endif
1393 #if defined(ETH_FBSD)
1394 "fbsd",
1395 #endif
1396 #ifdef ETH_ARPBACK
1397 "arpback",
1398 #endif
1399 #if HAVE_VDE
1400 "vde",
1401 #endif
1402 "vnet",
1403 NULL
1405 // ne2k options
1406 menu = new bx_list_c(network, "ne2k", "NE2000", 7);
1407 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1408 menu->set_enabled(BX_SUPPORT_NE2K);
1409 enabled = new bx_param_bool_c(menu,
1410 "enabled",
1411 "Enable NE2K NIC emulation",
1412 "Enables the NE2K NIC emulation",
1414 enabled->set_enabled(BX_SUPPORT_NE2K);
1415 ioaddr = new bx_param_num_c(menu,
1416 "ioaddr",
1417 "NE2K I/O Address",
1418 "I/O base address of the emulated NE2K device",
1419 0, 0xffff,
1420 0x300);
1421 ioaddr->set_base(16);
1422 irq = new bx_param_num_c(menu,
1423 "irq",
1424 "NE2K Interrupt",
1425 "IRQ used by the NE2K device",
1426 0, 15,
1428 irq->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1429 macaddr = new bx_param_string_c(menu,
1430 "macaddr",
1431 "MAC Address",
1432 "MAC address of the NE2K device. Don't use an address of a machine on your net.",
1433 "\xfe\xfd\xde\xad\xbe\xef", 6);
1434 macaddr->get_options()->set(bx_param_string_c::RAW_BYTES);
1435 macaddr->set_separator(':');
1436 ethmod = new bx_param_enum_c(menu,
1437 "ethmod",
1438 "Ethernet module",
1439 "Module used for the connection to the real net.",
1440 eth_module_list,
1443 ethmod->set_by_name("null");
1444 ethmod->set_ask_format("Choose ethernet module for the NE2K [%s] ");
1445 ethdev = new bx_param_string_c(menu,
1446 "ethdev",
1447 "Ethernet device",
1448 "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
1449 "xl0", BX_PATHNAME_LEN);
1450 path = new bx_param_filename_c(menu,
1451 "script",
1452 "Device configuration script",
1453 "Name of the script that is executed after Bochs initializes the network interface (optional).",
1454 "none", BX_PATHNAME_LEN);
1455 path->set_ask_format("Enter new script name, or 'none': [%s] ");
1456 enabled->set_dependent_list(menu->clone());
1457 // pnic options
1458 menu = new bx_list_c(network, "pnic", "PCI Pseudo NIC");
1459 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1460 menu->set_enabled(BX_SUPPORT_PCIPNIC);
1461 enabled = new bx_param_bool_c(menu,
1462 "enabled",
1463 "Enable Pseudo NIC emulation",
1464 "Enables the Pseudo NIC emulation",
1466 enabled->set_enabled(BX_SUPPORT_PCIPNIC);
1467 macaddr = new bx_param_string_c(menu,
1468 "macaddr",
1469 "MAC Address",
1470 "MAC address of the Pseudo NIC device. Don't use an address of a machine on your net.",
1471 "\xfe\xfd\xde\xad\xbe\xef", 6);
1472 macaddr->get_options()->set(bx_param_string_c::RAW_BYTES);
1473 macaddr->set_separator(':');
1474 ethmod = new bx_param_enum_c(menu,
1475 "ethmod",
1476 "Ethernet module",
1477 "Module used for the connection to the real net.",
1478 eth_module_list,
1481 ethmod->set_by_name("null");
1482 ethmod->set_ask_format("Choose ethernet module for the Pseudo NIC [%s]");
1483 ethdev = new bx_param_string_c(menu,
1484 "ethdev",
1485 "Ethernet device",
1486 "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
1487 "xl0", BX_PATHNAME_LEN);
1488 path = new bx_param_filename_c(menu,
1489 "script",
1490 "Device configuration script",
1491 "Name of the script that is executed after Bochs initializes the network interface (optional).",
1492 "none", BX_PATHNAME_LEN);
1493 path->set_ask_format("Enter new script name, or 'none': [%s] ");
1494 enabled->set_dependent_list(menu->clone());
1496 // sound subtree
1497 bx_list_c *sound = new bx_list_c(root_param, "sound", "Sound Configuration");
1498 sound->get_options()->set(bx_list_c::SHOW_PARENT);
1499 menu = new bx_list_c(sound, "sb16", "SB16 Configuration", 8);
1500 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1501 menu->set_enabled(BX_SUPPORT_SB16);
1503 // SB16 options
1504 enabled = new bx_param_bool_c(menu,
1505 "enabled",
1506 "Enable SB16 emulation",
1507 "Enables the SB16 emulation",
1509 enabled->set_enabled(BX_SUPPORT_SB16);
1510 bx_param_num_c *midimode = new bx_param_num_c(menu,
1511 "midimode",
1512 "Midi mode",
1513 "Controls the MIDI output format.",
1514 0, 3,
1516 bx_param_filename_c *midifile = new bx_param_filename_c(menu,
1517 "midifile",
1518 "MIDI file",
1519 "The filename is where the MIDI data is sent. This can be device or just a file.",
1520 "", BX_PATHNAME_LEN);
1521 bx_param_num_c *wavemode = new bx_param_num_c(menu,
1522 "wavemode",
1523 "Wave mode",
1524 "Controls the wave output format.",
1525 0, 3,
1527 bx_param_filename_c *wavefile = new bx_param_filename_c(menu,
1528 "wavefile",
1529 "Wave file",
1530 "This is the device/file where the wave output is stored",
1531 "", BX_PATHNAME_LEN);
1532 bx_param_num_c *loglevel = new bx_param_num_c(menu,
1533 "loglevel",
1534 "Log level",
1535 "Controls how verbose the SB16 emulation is (0 = no log, 5 = all errors and infos).",
1536 0, 5,
1538 bx_param_filename_c *logfile = new bx_param_filename_c(menu,
1539 "logfile",
1540 "Log file",
1541 "The file to write the SB16 emulator messages to.",
1542 "", BX_PATHNAME_LEN);
1543 bx_param_num_c *dmatimer = new bx_param_num_c(menu,
1544 "dmatimer",
1545 "DMA timer",
1546 "Microseconds per second for a DMA cycle.",
1547 0, BX_MAX_BIT32U,
1550 #if BX_WITH_WX
1551 midimode->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1552 wavemode->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1553 loglevel->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1554 #endif
1555 loglevel->set_group("SB16");
1556 dmatimer->set_group("SB16");
1557 enabled->set_dependent_list(menu->clone());
1558 deplist = new bx_list_c(NULL, 1);
1559 deplist->add(midifile);
1560 midimode->set_dependent_list(deplist);
1561 deplist = new bx_list_c(NULL, 1);
1562 deplist->add(wavefile);
1563 wavemode->set_dependent_list(deplist);
1564 deplist = new bx_list_c(NULL, 1);
1565 deplist->add(logfile);
1566 loglevel->set_dependent_list(deplist);
1568 // misc options subtree
1569 bx_list_c *misc = new bx_list_c(root_param, "misc", "Configure Everything Else");
1570 misc->get_options()->set(bx_list_c::SHOW_PARENT);
1571 bx_param_num_c *gdbstub_opt;
1573 // text snapshot check panic
1574 new bx_param_bool_c(misc,
1575 "text_snapshot_check",
1576 "Enable text snapshot check panic",
1577 "Enable panic when text on screen matches snapchk.txt.\nUseful for regression testing.\nIn win32, turns off CR/LF in snapshots and cuts.",
1579 // GDB stub
1580 menu = new bx_list_c(misc, "gdbstub", "GDB Stub Options");
1581 menu->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
1582 menu->set_enabled(BX_GDBSTUB);
1583 enabled = new bx_param_bool_c(menu,
1584 "enabled",
1585 "Enable GDB stub",
1588 enabled->set_enabled(BX_GDBSTUB);
1589 gdbstub_opt = new bx_param_num_c(menu,
1590 "port",
1591 "Port",
1592 "TCP/IP port for GDB stub",
1593 0, 65535,
1594 1234);
1595 gdbstub_opt = new bx_param_num_c(menu,
1596 "text_base",
1597 "Text base",
1599 0, BX_MAX_BIT32U,
1601 gdbstub_opt = new bx_param_num_c(menu,
1602 "data_base",
1603 "Data base",
1605 0, BX_MAX_BIT32U,
1607 gdbstub_opt = new bx_param_num_c(menu,
1608 "bss_base",
1609 "BSS base",
1611 0, BX_MAX_BIT32U,
1613 enabled->set_dependent_list(menu->clone());
1615 // log options subtree
1616 menu = new bx_list_c(root_param, "log", "Logfile Options");
1618 // log options
1619 path = new bx_param_filename_c(menu,
1620 "filename",
1621 "Log filename",
1622 "Pathname of bochs log file",
1623 "-", BX_PATHNAME_LEN);
1624 path->set_ask_format("Enter log filename: [%s] ");
1626 bx_param_string_c *prefix = new bx_param_string_c(menu,
1627 "prefix",
1628 "Log output prefix",
1629 "Prefix prepended to log output",
1630 "%t%e%d", BX_PATHNAME_LEN);
1631 prefix->set_ask_format("Enter log prefix: [%s] ");
1633 path = new bx_param_filename_c(menu,
1634 "debugger_filename",
1635 "Debugger Log filename",
1636 "Pathname of debugger log file",
1637 "-", BX_PATHNAME_LEN);
1638 path->set_ask_format("Enter debugger log filename: [%s] ");
1639 path->set_enabled(BX_DEBUGGER);
1641 // runtime options
1642 bx_param_c *runtime_init_list[] = {
1643 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL),
1644 SIM->get_param_bool(BXPN_MOUSE_ENABLED),
1645 SIM->get_param_num(BXPN_KBD_PASTE_DELAY),
1646 SIM->get_param_string(BXPN_USER_SHORTCUT),
1647 SIM->get_param_num(BXPN_SB16_DMATIMER),
1648 SIM->get_param_num(BXPN_SB16_LOGLEVEL),
1649 SIM->get_param_string(BXPN_USB1_PORT1),
1650 SIM->get_param_string(BXPN_USB1_PORT2),
1651 NULL
1653 menu = new bx_list_c(special_menus, "runtime", "Misc runtime options", runtime_init_list);
1654 menu->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::SHOW_GROUP_NAME);
1657 void bx_reset_options()
1659 // cpu
1660 SIM->get_param("cpu")->reset();
1662 // memory (ram & rom)
1663 SIM->get_param("memory")->reset();
1665 // clock & cmos
1666 SIM->get_param("clock_cmos")->reset();
1668 // pci
1669 SIM->get_param("pci")->reset();
1671 // display & interface
1672 SIM->get_param("display")->reset();
1674 // keyboard & mouse
1675 SIM->get_param("keyboard_mouse")->reset();
1677 // boot
1678 SIM->get_param("boot_params")->reset();
1680 // floppy drives
1681 SIM->get_param("floppy")->reset();
1683 // ata/atapi drives
1684 SIM->get_param("ata")->reset();
1686 // standard ports
1687 SIM->get_param("ports")->reset();
1689 // ne2k & pnic
1690 SIM->get_param("network")->reset();
1692 // SB16
1693 SIM->get_param("sound")->reset();
1695 // misc
1696 SIM->get_param("misc")->reset();
1698 // logfile
1699 SIM->get_param("log")->reset();
1702 int bx_read_configuration(const char *rcfile)
1704 // parse rcfile first, then parse arguments in order.
1705 BX_INFO (("reading configuration from %s", rcfile));
1706 if (parse_bochsrc(rcfile) < 0) {
1707 BX_PANIC (("reading from %s failed", rcfile));
1708 return -1;
1710 // update log actions
1711 for (int level=0; level<N_LOGLEV; level++) {
1712 int action = SIM->get_default_log_action(level);
1713 io->set_log_action(level, action);
1715 return 0;
1718 int bx_parse_cmdline(int arg, int argc, char *argv[])
1720 //if (arg < argc) BX_INFO (("parsing command line arguments"));
1722 while (arg < argc) {
1723 BX_INFO (("parsing arg %d, %s", arg, argv[arg]));
1724 parse_line_unformatted("cmdline args", argv[arg]);
1725 arg++;
1727 // update log actions
1728 for (int level=0; level<N_LOGLEV; level++) {
1729 int action = SIM->get_default_log_action(level);
1730 io->set_log_action(level, action);
1732 return 0;
1735 #if BX_PROVIDE_MAIN
1736 char *bx_find_bochsrc()
1738 FILE *fd = NULL;
1739 char rcfile[512];
1740 Bit32u retry = 0, found = 0;
1741 // try several possibilities for the bochsrc before giving up
1742 while (!found) {
1743 rcfile[0] = 0;
1744 switch (retry++) {
1745 case 0: strcpy (rcfile, ".bochsrc"); break;
1746 case 1: strcpy (rcfile, "bochsrc"); break;
1747 case 2: strcpy (rcfile, "bochsrc.txt"); break;
1748 #ifdef WIN32
1749 case 3: strcpy (rcfile, "bochsrc.bxrc"); break;
1750 #elif !BX_WITH_MACOS
1751 // only try this on unix
1752 case 3:
1754 char *ptr = getenv("HOME");
1755 if (ptr) snprintf (rcfile, sizeof(rcfile), "%s/.bochsrc", ptr);
1757 break;
1758 case 4: strcpy (rcfile, "/etc/bochsrc"); break;
1759 #endif
1760 default:
1761 return NULL;
1763 if (rcfile[0]) {
1764 BX_DEBUG (("looking for configuration in %s", rcfile));
1765 fd = fopen(rcfile, "r");
1766 if (fd) found = 1;
1769 assert (fd != NULL && rcfile[0] != 0);
1770 fclose (fd);
1771 return strdup(rcfile);
1774 static int parse_bochsrc(const char *rcfile)
1776 FILE *fd = NULL;
1777 char *ret;
1778 char line[512];
1779 char context[BX_PATHNAME_LEN];
1780 Bit32u linenum = 1;
1782 // try several possibilities for the bochsrc before giving up
1784 bochsrc_include_count++;
1786 fd = fopen (rcfile, "r");
1787 if (fd == NULL) return -1;
1789 int retval = 0;
1790 do {
1791 ret = fgets(line, sizeof(line)-1, fd);
1792 line[sizeof(line) - 1] = '\0';
1793 size_t len = strlen(line);
1794 if ((len>0) && (line[len-1] < ' '))
1795 line[len-1] = '\0';
1796 if ((ret != NULL) && strlen(line)) {
1797 sprintf(context, "%s:%u", rcfile, linenum);
1798 if (parse_line_unformatted(context, line) < 0) {
1799 retval = -1;
1800 break; // quit parsing after first error
1803 linenum++;
1804 } while (!feof(fd));
1805 fclose(fd);
1806 bochsrc_include_count--;
1807 return retval;
1810 static const char *get_builtin_variable(const char *varname)
1812 #ifdef WIN32
1813 int code;
1814 DWORD size;
1815 DWORD type = 0;
1816 HKEY hkey;
1817 char keyname[80];
1818 static char data[MAX_PATH];
1819 #endif
1821 if (strlen(varname)<1) return NULL;
1822 else {
1823 if (!strcmp(varname, "BXSHARE")) {
1824 #ifdef WIN32
1825 wsprintf(keyname, "Software\\Bochs %s", VER_STRING);
1826 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey);
1827 if (code == ERROR_SUCCESS) {
1828 data[0] = 0;
1829 size = MAX_PATH;
1830 if (RegQueryValueEx(hkey, "", NULL, (LPDWORD)&type, (LPBYTE)data,
1831 (LPDWORD)&size) == ERROR_SUCCESS) {
1832 RegCloseKey(hkey);
1833 return data;
1834 } else {
1835 RegCloseKey(hkey);
1836 return NULL;
1838 } else {
1839 return NULL;
1841 #else
1842 return BX_SHARE_PATH;
1843 #endif
1845 return NULL;
1849 static int parse_line_unformatted(const char *context, char *line)
1851 #define MAX_PARAMS_LEN 40
1852 char *ptr;
1853 unsigned i, string_i = 0;
1854 char string[512];
1855 char *params[MAX_PARAMS_LEN];
1856 int num_params;
1857 bx_bool inquotes = 0;
1858 bx_bool comment = 0;
1860 memset(params, 0, sizeof(params));
1861 if (line == NULL) return 0;
1863 // if passed nothing but whitespace, just return
1864 for (i=0; i<strlen(line); i++) {
1865 if (!isspace(line[i])) break;
1867 if (i>=strlen(line))
1868 return 0;
1870 num_params = 0;
1872 if (!strncmp(line, "#include", 8))
1873 ptr = strtok(line, " ");
1874 else
1875 ptr = strtok(line, ":");
1876 while ((ptr) && (!comment)) {
1877 if (!inquotes) {
1878 string_i = 0;
1879 } else {
1880 string[string_i++] = ',';
1882 for (i=0; i<strlen(ptr); i++) {
1883 if (ptr[i] == '"')
1884 inquotes = !inquotes;
1885 else if ((ptr[i] == '#') && (strncmp(line+i, "#include", 8)) && !inquotes) {
1886 comment = 1;
1887 break;
1888 } else {
1889 #if BX_HAVE_GETENV
1890 // substitute environment variables.
1891 if (ptr[i] == '$') {
1892 char varname[512];
1893 char *pv = varname;
1894 const char *value;
1895 *pv = 0;
1896 i++;
1897 while (isalpha(ptr[i]) || ptr[i]=='_') {
1898 *pv = ptr[i]; pv++; i++;
1900 *pv = 0;
1901 if (strlen(varname)<1 || !(value = getenv(varname))) {
1902 if ((value = get_builtin_variable(varname))) {
1903 // append value to the string
1904 for (pv=(char *)value; *pv; pv++)
1905 string[string_i++] = *pv;
1906 } else {
1907 BX_PANIC (("could not look up environment variable '%s'", varname));
1909 } else {
1910 // append value to the string
1911 for (pv=(char *)value; *pv; pv++)
1912 string[string_i++] = *pv;
1915 #endif
1916 if (!isspace(ptr[i]) || inquotes) {
1917 string[string_i++] = ptr[i];
1921 string[string_i] = '\0';
1922 if (string_i == 0) break;
1923 if (!inquotes) {
1924 if (params[num_params] != NULL) {
1925 free(params[num_params]);
1926 params[num_params] = NULL;
1928 if (num_params < MAX_PARAMS_LEN) {
1929 params[num_params++] = strdup(string);
1930 } else {
1931 BX_PANIC (("too many parameters, max is %d\n", MAX_PARAMS_LEN));
1934 ptr = strtok(NULL, ",");
1936 Bit32s retval = parse_line_formatted(context, num_params, &params[0]);
1937 for (i=0; i < MAX_PARAMS_LEN; i++)
1939 if (params[i] != NULL)
1941 free(params[i]);
1942 params[i] = NULL;
1945 return retval;
1948 // These macros are called for all parse errors, so that we can easily
1949 // change the behavior of all occurrences.
1950 #define PARSE_ERR(x) \
1951 do { BX_PANIC(x); return -1; } while (0)
1952 #define PARSE_WARN(x) \
1953 BX_ERROR(x)
1956 * this supports the "floppyx: image=" option.
1957 * the functions returns the type of the floppy
1958 * image (1.44, 360, etc.), based on the image file size.
1960 int get_floppy_type_from_image(const char *filename)
1962 struct stat stat_buf;
1964 if (stat(filename, &stat_buf))
1966 return BX_FLOPPY_NONE;
1969 switch (stat_buf.st_size)
1971 case 163840:
1972 return BX_FLOPPY_160K;
1974 case 184320:
1975 return BX_FLOPPY_180K;
1977 case 327680:
1978 return BX_FLOPPY_320K;
1980 case 368640:
1981 return BX_FLOPPY_360K;
1983 case 737280:
1984 return BX_FLOPPY_720K;
1986 case 1228800:
1987 return BX_FLOPPY_1_2;
1989 case 1474560:
1990 case 1720320:
1991 case 1763328:
1992 case 1884160:
1993 return BX_FLOPPY_1_44;
1995 case 2949120:
1996 return BX_FLOPPY_2_88;
1998 default:
1999 return BX_FLOPPY_UNKNOWN;
2003 static Bit32s parse_log_options(const char *context, char *loglev, char *param1)
2005 int level;
2007 if (!strcmp(loglev, "panic")) {
2008 level = LOGLEV_PANIC;
2009 } else if (!strcmp(loglev, "pass")) {
2010 level = LOGLEV_PASS;
2011 } else if (!strcmp(loglev, "error")) {
2012 level = LOGLEV_ERROR;
2013 } else if (!strcmp(loglev, "info")) {
2014 level = LOGLEV_INFO;
2015 } else { /* debug */
2016 level = LOGLEV_DEBUG;
2018 if (strncmp(param1, "action=", 7)) {
2019 PARSE_ERR(("%s: %s directive malformed.", context, loglev));
2021 char *action = param1 + 7;
2022 if (!strcmp(action, "fatal"))
2023 SIM->set_default_log_action(level, ACT_FATAL);
2024 else if (!strcmp (action, "report"))
2025 SIM->set_default_log_action(level, ACT_REPORT);
2026 else if (!strcmp (action, "ignore"))
2027 SIM->set_default_log_action(level, ACT_IGNORE);
2028 else if (!strcmp (action, "ask"))
2029 SIM->set_default_log_action(level, ACT_ASK);
2030 else {
2031 PARSE_ERR(("%s: %s directive malformed.", context, loglev));
2033 return 0;
2036 static int parse_debug_symbols(const char *context, char **params, int num_params)
2038 #if BX_DEBUGGER
2039 Bit32u offset = 0;
2040 char* filename = 0;
2042 while (num_params > 0)
2044 if (!strncmp(*params, "file=", 5)) {
2045 filename = *params + 5;
2047 else if (!strncmp(*params, "offset=", 7)) {
2048 char* end;
2049 offset = strtoul(*params + 7, &end, 0);
2050 if (*end)
2051 PARSE_ERR(("%s: debug_symbols: invalid parameter %s", context, *params));
2053 else {
2054 PARSE_ERR(("%s: debug_symbols: invalid parameter %s", context, *params));
2056 params++; num_params--;
2059 if (!filename)
2060 PARSE_ERR(("%s: debug_symbols: missing file name", context));
2062 if (bx_dbg_symbol_command(filename, 1, offset) < 0)
2063 PARSE_ERR(("%s: debug_symbols: failed to load symbols from '%s'", context, filename));
2064 #endif
2065 return 0;
2068 static int parse_line_formatted(const char *context, int num_params, char *params[])
2070 int i, slot, t;
2071 Bit8u idx;
2072 bx_list_c *base;
2074 if (num_params < 1) return 0;
2075 if (num_params < 2) {
2076 PARSE_ERR(("%s: a bochsrc option needs at least one parameter", context));
2079 if (!strcmp(params[0], "#include")) {
2080 if (num_params != 2) {
2081 PARSE_ERR(("%s: ignoring malformed #include directive.", context));
2083 if (!strcmp(params[1], context)) {
2084 PARSE_ERR(("%s: cannot include this file again.", context));
2086 if (bochsrc_include_count == 2) {
2087 PARSE_ERR(("%s: include directive in an included file not supported yet.", context));
2089 bx_read_configuration(params[1]);
2091 else if (!strcmp(params[0], "floppya")) {
2092 for (i=1; i<num_params; i++) {
2093 if (!strncmp(params[i], "2_88=", 5)) {
2094 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2095 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_2_88);
2097 else if (!strncmp(params[i], "1_44=", 5)) {
2098 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2099 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_1_44);
2101 else if (!strncmp(params[i], "1_2=", 4)) {
2102 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][4]);
2103 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_1_2);
2105 else if (!strncmp(params[i], "720k=", 5)) {
2106 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2107 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_720K);
2109 else if (!strncmp(params[i], "360k=", 5)) {
2110 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2111 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_360K);
2113 // use CMOS reserved types?
2114 else if (!strncmp(params[i], "160k=", 5)) {
2115 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2116 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_160K);
2118 else if (!strncmp(params[i], "180k=", 5)) {
2119 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2120 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_180K);
2122 else if (!strncmp(params[i], "320k=", 5)) {
2123 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2124 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_320K);
2126 else if (!strncmp(params[i], "image=", 6)) {
2127 /* "image=" means we should get floppy type from image */
2128 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][6]);
2129 t = get_floppy_type_from_image(&params[i][6]);
2130 if (t != BX_FLOPPY_UNKNOWN)
2131 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(t);
2132 else
2133 PARSE_ERR(("%s: floppya image size doesn't match one of the supported types.", context));
2135 else if (!strncmp(params[i], "status=", 7)) {
2136 SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->set_by_name(&params[i][7]);
2138 else {
2139 PARSE_ERR(("%s: floppya attribute '%s' not understood.", context,
2140 params[i]));
2145 else if (!strcmp(params[0], "floppyb")) {
2146 for (i=1; i<num_params; i++) {
2147 if (!strncmp(params[i], "2_88=", 5)) {
2148 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2149 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_2_88);
2151 else if (!strncmp(params[i], "1_44=", 5)) {
2152 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2153 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_1_44);
2155 else if (!strncmp(params[i], "1_2=", 4)) {
2156 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][4]);
2157 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_1_2);
2159 else if (!strncmp(params[i], "720k=", 5)) {
2160 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2161 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_720K);
2163 else if (!strncmp(params[i], "360k=", 5)) {
2164 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2165 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_360K);
2167 // use CMOS reserved types?
2168 else if (!strncmp(params[i], "160k=", 5)) {
2169 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2170 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_160K);
2172 else if (!strncmp(params[i], "180k=", 5)) {
2173 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2174 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_180K);
2176 else if (!strncmp(params[i], "320k=", 5)) {
2177 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2178 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_320K);
2180 else if (!strncmp(params[i], "image=", 6)) {
2181 /* "image=" means we should get floppy type from image */
2182 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][6]);
2183 t = get_floppy_type_from_image(&params[i][6]);
2184 if (t != BX_FLOPPY_UNKNOWN)
2185 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(t);
2186 else
2187 PARSE_ERR(("%s: floppyb image size doesn't match one of the supported types.", context));
2189 else if (!strncmp(params[i], "status=", 7)) {
2190 SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->set_by_name(&params[i][7]);
2192 else {
2193 PARSE_ERR(("%s: floppyb attribute '%s' not understood.", context,
2194 params[i]));
2199 else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) {
2200 char tmpname[80];
2201 Bit8u channel = params[0][3];
2203 if ((channel < '0') || (channel > '9')) {
2204 PARSE_ERR(("%s: ataX directive malformed.", context));
2206 channel-='0';
2207 if (channel >= BX_MAX_ATA_CHANNEL) {
2208 PARSE_ERR(("%s: ataX directive malformed.", context));
2211 if ((num_params < 2) || (num_params > 5)) {
2212 PARSE_ERR(("%s: ataX directive malformed.", context));
2214 sprintf(tmpname, "ata.%d.resources", channel);
2215 base = (bx_list_c*) SIM->get_param(tmpname);
2216 if (strncmp(params[1], "enabled=", 8)) {
2217 PARSE_ERR(("%s: ataX directive malformed.", context));
2218 } else {
2219 SIM->get_param_bool("enabled", base)->set(atol(&params[1][8]));
2222 if (num_params > 2) {
2223 if (strncmp(params[2], "ioaddr1=", 8)) {
2224 PARSE_ERR(("%s: ataX directive malformed.", context));
2226 else {
2227 if ((params[2][8] == '0') && (params[2][9] == 'x'))
2228 SIM->get_param_num("ioaddr1", base)->set(strtoul(&params[2][8], NULL, 16));
2229 else
2230 SIM->get_param_num("ioaddr1", base)->set(strtoul(&params[2][8], NULL, 10));
2234 if (num_params > 3) {
2235 if (strncmp(params[3], "ioaddr2=", 8)) {
2236 PARSE_ERR(("%s: ataX directive malformed.", context));
2238 else {
2239 if ((params[3][8] == '0') && (params[3][9] == 'x'))
2240 SIM->get_param_num("ioaddr2", base)->set(strtoul(&params[3][8], NULL, 16));
2241 else
2242 SIM->get_param_num("ioaddr2", base)->set(strtoul(&params[3][8], NULL, 10));
2246 if (num_params > 4) {
2247 if (strncmp(params[4], "irq=", 4)) {
2248 PARSE_ERR(("%s: ataX directive malformed.", context));
2250 else {
2251 SIM->get_param_num("irq", base)->set(atol(&params[4][4]));
2256 // ataX-master, ataX-slave
2257 else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) {
2258 Bit8u channel = params[0][3];
2259 int type = 0, mode = BX_ATA_MODE_FLAT, biosdetect = BX_ATA_BIOSDETECT_AUTO;
2260 Bit32u cylinders = 0, heads = 0, sectors = 0;
2261 char tmpname[80];
2263 if ((channel < '0') || (channel > '9')) {
2264 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2266 channel-='0';
2267 if (channel >= BX_MAX_ATA_CHANNEL) {
2268 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2271 if ((strcmp(&params[0][4], "-slave")) &&
2272 (strcmp(&params[0][4], "-master"))) {
2273 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2276 sprintf(tmpname, "ata.%d.%s", channel, &params[0][5]);
2277 base = (bx_list_c*) SIM->get_param(tmpname);
2278 for (i=1; i<num_params; i++) {
2279 if (!strncmp(params[i], "type=", 5)) {
2280 type = SIM->get_param_enum("type", base)->find_by_name(&params[i][5]);
2281 if (type < 0) {
2282 PARSE_ERR(("%s: ataX-master/slave: unknown type '%s'", context, &params[i][5]));
2284 } else if (!strcmp(params[i], "mode=z-undoable")) {
2285 PARSE_ERR(("%s: ataX-master/slave mode 'z-undoable' not implemented yet", context));
2286 } else if (!strcmp(params[i], "mode=z-volatile")) {
2287 PARSE_ERR(("%s: ataX-master/slave mode 'z-volatile' not implemented yet", context));
2288 } else if (!strncmp(params[i], "mode=", 5)) {
2289 mode = SIM->get_param_enum("mode", base)->find_by_name(&params[i][5]);
2290 if (mode < 0) {
2291 PARSE_ERR(("%s: ataX-master/slave: unknown mode '%s'", context, &params[i][5]));
2293 } else if (!strncmp(params[i], "path=", 5)) {
2294 SIM->get_param_string("path", base)->set(&params[i][5]);
2295 } else if (!strncmp(params[i], "cylinders=", 10)) {
2296 cylinders = atol(&params[i][10]);
2297 } else if (!strncmp(params[i], "heads=", 6)) {
2298 heads = atol(&params[i][6]);
2299 } else if (!strncmp(params[i], "spt=", 4)) {
2300 sectors = atol(&params[i][4]);
2301 } else if (!strncmp(params[i], "model=", 6)) {
2302 SIM->get_param_string("model", base)->set(&params[i][6]);
2303 } else if (!strncmp(params[i], "biosdetect=", 11)) {
2304 biosdetect = SIM->get_param_enum("biosdetect", base)->find_by_name(&params[i][11]);
2305 if (biosdetect < 0) {
2306 PARSE_ERR(("%s: ataX-master/slave: unknown biosdetect '%s'", context, &params[i][11]));
2308 } else if (!strcmp(params[i], "translation=none")) {
2309 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_NONE);
2310 } else if (!strcmp(params[i], "translation=lba")) {
2311 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LBA);
2312 } else if (!strcmp(params[i], "translation=large")) {
2313 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE);
2314 } else if (!strcmp(params[i], "translation=echs")) { // synonym of large
2315 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE);
2316 } else if (!strcmp(params[i], "translation=rechs")) {
2317 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_RECHS);
2318 } else if (!strcmp(params[i], "translation=auto")) {
2319 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_AUTO);
2320 } else if (!strcmp(params[i], "status=ejected")) {
2321 SIM->get_param_enum("status", base)->set(BX_EJECTED);
2322 } else if (!strcmp(params[i], "status=inserted")) {
2323 SIM->get_param_enum("status", base)->set(BX_INSERTED);
2324 } else if (!strncmp(params[i], "journal=", 8)) {
2325 SIM->get_param_string("journal", base)->set(&params[i][8]);
2326 } else {
2327 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2331 // Enables the ata device
2332 if (strlen(SIM->get_param_string("path", base)->getptr()) > 0) {
2333 SIM->get_param_bool("present", base)->set(1);
2334 SIM->get_param_enum("type", base)->set(type);
2335 SIM->get_param_enum("mode", base)->set(mode);
2336 SIM->get_param_num("cylinders", base)->set(cylinders);
2337 SIM->get_param_num("heads", base)->set(heads);
2338 SIM->get_param_num("spt", base)->set(sectors);
2339 SIM->get_param_num("biosdetect", base)->set(biosdetect);
2340 } else {
2341 SIM->get_param_bool("present", base)->set(0);
2344 // if enabled, check if device ok
2345 if (SIM->get_param_bool("present", base)->get() == 1) {
2346 if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) {
2347 if ((SIM->get_param_num("cylinders", base)->get() == 0) &&
2348 (SIM->get_param_num("heads", base)->get() == 0) &&
2349 (SIM->get_param_num("spt", base)->get() == 0)) {
2350 PARSE_WARN(("%s: ataX-master/slave CHS set to 0/0/0 - autodetection enabled", context));
2351 // using heads = 16 and spt = 63 for autodetection (bximage defaults)
2352 SIM->get_param_num("heads", base)->set(16);
2353 SIM->get_param_num("spt", base)->set(63);
2355 } else if (SIM->get_param_enum("type", base)->get() != BX_ATA_DEVICE_CDROM) {
2356 PARSE_WARN(("%s: ataX-master/slave: type should be specified", context));
2359 } else if (!strcmp(params[0], "boot")) {
2360 char tmppath[80];
2361 if (num_params < 2) {
2362 PARSE_ERR(("%s: boot directive malformed.", context));
2364 for (i=1; i<num_params; i++) {
2365 sprintf(tmppath, "boot_params.boot_drive%d", i);
2366 if (!strcmp(params[i], "none")) {
2367 SIM->get_param_enum(tmppath)->set(BX_BOOT_NONE);
2368 } else if (!strcmp(params[i], "a")) {
2369 SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA);
2370 } else if (!strcmp(params[i], "floppy")) {
2371 SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA);
2372 } else if (!strcmp(params[i], "c")) {
2373 SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC);
2374 } else if (!strcmp(params[i], "disk")) {
2375 SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC);
2376 } else if (!strcmp(params[i], "cdrom")) {
2377 SIM->get_param_enum(tmppath)->set(BX_BOOT_CDROM);
2378 } else if (!strcmp(params[i], "network")) {
2379 SIM->get_param_enum(tmppath)->set(BX_BOOT_NETWORK);
2380 } else {
2381 PARSE_ERR(("%s: boot directive with unknown boot drive '%s'. use 'floppy', 'disk', 'cdrom' or 'network'.", context, params[i]));
2384 if (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == BX_BOOT_NONE) {
2385 PARSE_ERR(("%s: first boot drive must be one of 'floppy', 'disk' or 'cdrom'.", context));
2387 if ((SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE2)->get()) ||
2388 (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()) ||
2389 ((SIM->get_param_enum(BXPN_BOOTDRIVE3)->get() != BX_BOOT_NONE) &&
2390 (SIM->get_param_enum(BXPN_BOOTDRIVE2)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()))) {
2391 PARSE_ERR(("%s: a boot drive appears twice in boot sequence.", context));
2393 } else if (!strcmp(params[0], "floppy_bootsig_check")) {
2394 if (num_params != 2) {
2395 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2397 if (strncmp(params[1], "disabled=", 9)) {
2398 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2400 if (params[1][9] == '0')
2401 SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->set(0);
2402 else if (params[1][9] == '1')
2403 SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->set(1);
2404 else {
2405 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2407 } else if (!strcmp(params[0], "log")) {
2408 if (num_params != 2) {
2409 PARSE_ERR(("%s: log directive has wrong # args.", context));
2411 SIM->get_param_string(BXPN_LOG_FILENAME)->set(params[1]);
2412 } else if (!strcmp(params[0], "logprefix")) {
2413 if (num_params != 2) {
2414 PARSE_ERR(("%s: logprefix directive has wrong # args.", context));
2416 SIM->get_param_string(BXPN_LOG_PREFIX)->set(params[1]);
2417 } else if (!strcmp(params[0], "debugger_log")) {
2418 if (num_params != 2) {
2419 PARSE_ERR(("%s: debugger_log directive has wrong # args.", context));
2421 SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->set(params[1]);
2422 } else if (!strcmp(params[0], "panic")) {
2423 if (num_params != 2) {
2424 PARSE_ERR(("%s: panic directive malformed.", context));
2426 if (parse_log_options(context, params[0], params[1]) < 0) {
2427 return -1;
2429 } else if (!strcmp(params[0], "pass")) {
2430 if (num_params != 2) {
2431 PARSE_ERR(("%s: pass directive malformed.", context));
2433 if (parse_log_options(context, params[0], params[1]) < 0) {
2434 return -1;
2436 } else if (!strcmp(params[0], "error")) {
2437 if (num_params != 2) {
2438 PARSE_ERR(("%s: error directive malformed.", context));
2440 if (parse_log_options(context, params[0], params[1]) < 0) {
2441 return -1;
2443 } else if (!strcmp(params[0], "info")) {
2444 if (num_params != 2) {
2445 PARSE_ERR(("%s: info directive malformed.", context));
2447 if (parse_log_options(context, params[0], params[1]) < 0) {
2448 return -1;
2450 } else if (!strcmp(params[0], "debug")) {
2451 if (num_params != 2) {
2452 PARSE_ERR(("%s: debug directive malformed.", context));
2454 if (parse_log_options(context, params[0], params[1]) < 0) {
2455 return -1;
2457 } else if (!strcmp(params[0], "cpu")) {
2458 if (num_params < 2) {
2459 PARSE_ERR(("%s: cpu directive malformed.", context));
2461 for (i=1; i<num_params; i++) {
2462 if (!strncmp(params[i], "count=", 6)) {
2463 unsigned processors = 1, cores = 1, threads = 1;
2464 sscanf(&params[i][6], "%u:%u:%u", &processors, &cores, &threads);
2465 unsigned smp_threads = cores*threads*processors;
2466 if (smp_threads > BX_MAX_SMP_THREADS_SUPPORTED) {
2467 PARSE_ERR(("%s: too many SMP threads defined, only %u threads supported",
2468 context, BX_MAX_SMP_THREADS_SUPPORTED));
2470 if (smp_threads < 1) {
2471 PARSE_ERR(("%s: at least one CPU thread should be defined, cpu directive malformed", context));
2473 SIM->get_param_num(BXPN_CPU_NPROCESSORS)->set(processors);
2474 SIM->get_param_num(BXPN_CPU_NCORES)->set(cores);
2475 SIM->get_param_num(BXPN_CPU_NTHREADS)->set(threads);
2476 } else if (!strncmp(params[i], "ips=", 4)) {
2477 SIM->get_param_num(BXPN_IPS)->set(atol(&params[i][4]));
2478 if (SIM->get_param_num(BXPN_IPS)->get() < BX_MIN_IPS) {
2479 PARSE_WARN(("%s: WARNING: ips is AWFULLY low!", context));
2481 #if BX_SUPPORT_SMP
2482 } else if (!strncmp(params[i], "quantum=", 8)) {
2483 SIM->get_param_num(BXPN_SMP_QUANTUM)->set(atol(&params[i][8]));
2484 #endif
2485 } else if (!strncmp(params[i], "reset_on_triple_fault=", 22)) {
2486 if (params[i][22] == '0' || params[i][22] == '1') {
2487 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->set(params[i][22] - '0');
2488 } else {
2489 PARSE_ERR(("%s: cpu directive malformed.", context));
2491 } else if (!strncmp(params[i], "cpuid_limit_winnt=", 18)) {
2492 if (params[i][18] == '0' || params[i][18] == '1') {
2493 SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->set(params[i][18] - '0');
2494 } else {
2495 PARSE_ERR(("%s: cpu directive malformed.", context));
2497 } else if (!strncmp(params[i], "vendor_string=", 14)) {
2498 if (strlen(&params[i][14]) != BX_CPUID_VENDOR_LEN) {
2499 PARSE_ERR(("%s: cpu directive malformed.", context));
2501 SIM->get_param_string(BXPN_VENDOR_STRING)->set(&params[i][14]);
2502 } else if (!strncmp(params[i], "brand_string=", 13)) {
2503 if (strlen(&params[i][13]) > BX_CPUID_BRAND_LEN) {
2504 PARSE_ERR(("%s: cpu directive malformed.", context));
2506 SIM->get_param_string(BXPN_BRAND_STRING)->set(&params[i][13]);
2507 } else {
2508 PARSE_ERR(("%s: cpu directive malformed.", context));
2511 } else if (!strcmp(params[0], "megs")) {
2512 if (num_params != 2) {
2513 PARSE_ERR(("%s: megs directive: wrong # args.", context));
2515 SIM->get_param_num(BXPN_MEM_SIZE)->set(atol(params[1]));
2516 } else if (!strcmp(params[0], "romimage")) {
2517 if ((num_params < 2) || (num_params > 3)) {
2518 PARSE_ERR(("%s: romimage directive: wrong # args.", context));
2520 if (!strncmp(params[1], "file=", 5)) {
2521 SIM->get_param_string(BXPN_ROM_PATH)->set(&params[1][5]);
2522 } else {
2523 PARSE_ERR(("%s: romimage directive malformed.", context));
2525 if (num_params == 3) {
2526 if (!strncmp(params[2], "address=", 8)) {
2527 if ((params[2][8] == '0') && (params[2][9] == 'x'))
2528 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(&params[2][8], NULL, 16));
2529 else
2530 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(&params[2][8], NULL, 10));
2531 } else {
2532 PARSE_ERR(("%s: romimage directive malformed.", context));
2534 } else {
2535 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(0);
2537 } else if (!strcmp(params[0], "vgaromimage")) {
2538 if (num_params != 2) {
2539 PARSE_ERR(("%s: vgaromimage directive: wrong # args.", context));
2541 if (!strncmp(params[1], "file=", 5)) {
2542 SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(&params[1][5]);
2543 } else {
2544 BX_INFO(("WARNING: syntax has changed, please use 'vgaromimage: file=...' now"));
2545 SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(params[1]);
2547 } else if (!strncmp(params[0], "optromimage", 11)) {
2548 int num = atoi(&params[0][11]);
2549 char tmppath[80], tmpaddr[80];
2550 if ((num < 1) || (num > BX_N_OPTROM_IMAGES)) {
2551 PARSE_ERR(("%s: optromimage%d: not supported", context, num));
2553 if (num_params != 3) {
2554 PARSE_ERR(("%s: optromimage%d directive: wrong # args.", context, num));
2556 sprintf(tmppath, "memory.optrom.%d.path", num);
2557 sprintf(tmpaddr, "memory.optrom.%d.addr", num);
2558 for (i=1; i<num_params; i++) {
2559 if (!strncmp(params[i], "file=", 5)) {
2560 SIM->get_param_string(tmppath)->set(&params[i][5]);
2561 } else if (!strncmp(params[i], "address=", 8)) {
2562 if ((params[i][8] == '0') && (params[2][9] == 'x'))
2563 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 16));
2564 else
2565 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 10));
2566 } else {
2567 PARSE_ERR(("%s: optromimage%d directive malformed.", context, num));
2570 } else if (!strncmp(params[0], "optramimage", 11)) {
2571 int num = atoi(&params[0][11]);
2572 char tmppath[80], tmpaddr[80];
2573 if ((num < 1) || (num > BX_N_OPTRAM_IMAGES)) {
2574 PARSE_ERR(("%s: optramimage%d: not supported", context, num));
2576 if (num_params != 3) {
2577 PARSE_ERR(("%s: optramimage%d directive: wrong # args.", context, num));
2579 sprintf(tmppath, "memory.optram.%d.path", num);
2580 sprintf(tmpaddr, "memory.optram.%d.addr", num);
2581 for (i=1; i<num_params; i++) {
2582 if (!strncmp(params[i], "file=", 5)) {
2583 SIM->get_param_string(tmppath)->set(&params[i][5]);
2584 } else if (!strncmp(params[i], "address=", 8)) {
2585 if ((params[i][8] == '0') && (params[2][9] == 'x'))
2586 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 16));
2587 else
2588 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 10));
2589 } else {
2590 PARSE_ERR(("%s: optramimage%d directive malformed.", context, num));
2593 } else if (!strcmp(params[0], "vga_update_interval")) {
2594 if (num_params != 2) {
2595 PARSE_ERR(("%s: vga_update_interval directive: wrong # args.", context));
2597 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->set(atol(params[1]));
2598 if (SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->get() < 50000) {
2599 BX_INFO(("%s: vga_update_interval seems awfully small!", context));
2601 } else if (!strcmp(params[0], "vga")) {
2602 if (num_params != 2) {
2603 PARSE_ERR(("%s: vga directive: wrong # args.", context));
2605 if (!strncmp(params[1], "extension=", 10)) {
2606 SIM->get_param_string(BXPN_VGA_EXTENSION)->set(&params[1][10]);
2608 } else if (!strcmp(params[0], "keyboard_serial_delay")) {
2609 if (num_params != 2) {
2610 PARSE_ERR(("%s: keyboard_serial_delay directive: wrong # args.", context));
2612 SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->set(atol(params[1]));
2613 if (SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get() < 5) {
2614 PARSE_ERR (("%s: keyboard_serial_delay not big enough!", context));
2616 } else if (!strcmp(params[0], "keyboard_paste_delay")) {
2617 if (num_params != 2) {
2618 PARSE_ERR(("%s: keyboard_paste_delay directive: wrong # args.", context));
2620 SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set(atol(params[1]));
2621 if (SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get() < 1000) {
2622 PARSE_ERR (("%s: keyboard_paste_delay not big enough!", context));
2624 } else if (!strcmp(params[0], "ips")) {
2625 PARSE_WARN(("%s: ips directive is DEPRECATED (use cpu directive parameter 'ips').", context));
2626 if (num_params != 2) {
2627 PARSE_ERR(("%s: ips directive: wrong # args.", context));
2629 SIM->get_param_num(BXPN_IPS)->set(atol(params[1]));
2630 if (SIM->get_param_num(BXPN_IPS)->get() < BX_MIN_IPS) {
2631 PARSE_WARN(("%s: WARNING: ips is AWFULLY low!", context));
2633 } else if (!strcmp(params[0], "text_snapshot_check")) {
2634 if (num_params != 2) {
2635 PARSE_ERR(("%s: text_snapshot_check directive: wrong # args.", context));
2637 if (!strncmp(params[1], "enabled=", 8)) {
2638 if (params[1][8] == '0' || params[1][8] == '1')
2639 SIM->get_param_bool(BXPN_TEXT_SNAPSHOT_CHECK)->set(params[1][8] - '0');
2640 else
2641 PARSE_ERR(("%s: text_snapshot_check directive malformed.", context));
2642 } else {
2643 PARSE_ERR(("%s: text_snapshot_check directive malformed.", context));
2645 } else if (!strcmp(params[0], "mouse")) {
2646 if (num_params < 2) {
2647 PARSE_ERR(("%s: mouse directive malformed.", context));
2649 for (i=1; i<num_params; i++) {
2650 if (!strncmp(params[i], "enabled=", 8)) {
2651 if (params[i][8] == '0' || params[i][8] == '1')
2652 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->set(params[i][8] - '0');
2653 else
2654 PARSE_ERR(("%s: mouse directive malformed.", context));
2655 } else if (!strncmp(params[i], "type=", 5)) {
2656 if (!SIM->get_param_enum(BXPN_MOUSE_TYPE)->set_by_name(&params[i][5]))
2657 PARSE_ERR(("%s: mouse type '%s' not available", context, &params[i][5]));
2658 } else {
2659 PARSE_ERR(("%s: mouse directive malformed.", context));
2662 } else if (!strcmp(params[0], "private_colormap")) {
2663 if (num_params != 2) {
2664 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2666 if (strncmp(params[1], "enabled=", 8)) {
2667 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2669 if (params[1][8] == '0' || params[1][8] == '1')
2670 SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->set(params[1][8] - '0');
2671 else {
2672 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2674 } else if (!strcmp(params[0], "fullscreen")) {
2675 #if BX_WITH_AMIGAOS
2676 if (num_params != 2) {
2677 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2679 if (strncmp(params[1], "enabled=", 8)) {
2680 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2682 if (params[1][8] == '0' || params[1][8] == '1') {
2683 SIM->get_param_bool(BXPN_FULLSCREEN)->set(params[1][8] - '0');
2684 } else {
2685 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2687 #endif
2688 } else if (!strcmp(params[0], "screenmode")) {
2689 #if BX_WITH_AMIGAOS
2690 if (num_params != 2) {
2691 PARSE_ERR(("%s: screenmode directive malformed.", context));
2693 if (strncmp(params[1], "name=", 5)) {
2694 PARSE_ERR(("%s: screenmode directive malformed.", context));
2696 SIM->get_param_string(BXPN_SCREENMODE)->set(&params[1][5]);
2697 #endif
2698 } else if (!strcmp(params[0], "sb16")) {
2699 int enable = 1;
2700 base = (bx_list_c*) SIM->get_param(BXPN_SB16);
2701 for (i=1; i<num_params; i++) {
2702 if (!strncmp(params[i], "enabled=", 8)) {
2703 enable = atol(&params[i][8]);
2704 } else if (!strncmp(params[i], "midi=", 5)) {
2705 SIM->get_param_string("midifile", base)->set(&params[i][5]);
2706 } else if (!strncmp(params[i], "midimode=", 9)) {
2707 SIM->get_param_num("midimode", base)->set(atol(&params[i][9]));
2708 } else if (!strncmp(params[i], "wave=", 5)) {
2709 SIM->get_param_string("wavefile", base)->set(&params[i][5]);
2710 } else if (!strncmp(params[i], "wavemode=", 9)) {
2711 SIM->get_param_num("wavemode", base)->set(atol(&params[i][9]));
2712 } else if (!strncmp(params[i], "log=", 4)) {
2713 SIM->get_param_string("logfile", base)->set(&params[i][4]);
2714 } else if (!strncmp(params[i], "loglevel=", 9)) {
2715 SIM->get_param_num("loglevel", base)->set(atol(&params[i][9]));
2716 } else if (!strncmp(params[i], "dmatimer=", 9)) {
2717 SIM->get_param_num("dmatimer", base)->set(atol(&params[i][9]));
2718 } else {
2719 BX_ERROR(("%s: unknown parameter for sb16 ignored.", context));
2722 if ((enable != 0) && (SIM->get_param_num("dmatimer", base)->get() > 0))
2723 SIM->get_param_bool("enabled", base)->set(1);
2724 else
2725 SIM->get_param_bool("enabled", base)->set(0);
2726 } else if ((!strncmp(params[0], "com", 3)) && (strlen(params[0]) == 4)) {
2727 char tmpname[80];
2728 idx = params[0][3];
2729 if ((idx < '1') || (idx > '9')) {
2730 PARSE_ERR(("%s: comX directive malformed.", context));
2732 idx -= '0';
2733 if (idx > BX_N_SERIAL_PORTS) {
2734 PARSE_ERR(("%s: comX port number out of range.", context));
2736 sprintf(tmpname, "ports.serial.%d", idx);
2737 base = (bx_list_c*) SIM->get_param(tmpname);
2738 for (i=1; i<num_params; i++) {
2739 if (!strncmp(params[i], "enabled=", 8)) {
2740 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2741 } else if (!strncmp(params[i], "mode=", 5)) {
2742 if (!SIM->get_param_enum("mode", base)->set_by_name(&params[i][5]))
2743 PARSE_ERR(("%s: com%d serial port mode '%s' not available", context, idx, &params[i][5]));
2744 SIM->get_param_bool("enabled", base)->set(1);
2745 } else if (!strncmp(params[i], "dev=", 4)) {
2746 SIM->get_param_string("dev", base)->set(&params[i][4]);
2747 SIM->get_param_bool("enabled", base)->set(1);
2748 } else {
2749 PARSE_ERR(("%s: unknown parameter for com%d ignored.", context, idx));
2752 } else if ((!strncmp(params[0], "parport", 7)) && (strlen(params[0]) == 8)) {
2753 char tmpname[80];
2754 idx = params[0][7];
2755 if ((idx < '1') || (idx > '9')) {
2756 PARSE_ERR(("%s: parportX directive malformed.", context));
2758 idx -= '0';
2759 if (idx > BX_N_PARALLEL_PORTS) {
2760 PARSE_ERR(("%s: parportX port number out of range.", context));
2762 sprintf(tmpname, "ports.parallel.%d", idx);
2763 base = (bx_list_c*) SIM->get_param(tmpname);
2764 for (i=1; i<num_params; i++) {
2765 if (!strncmp(params[i], "enabled=", 8)) {
2766 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2767 } else if (!strncmp(params[i], "file=", 5)) {
2768 SIM->get_param_string("outfile", base)->set(&params[i][5]);
2769 SIM->get_param_bool("enabled", base)->set(1);
2770 } else {
2771 BX_ERROR(("%s: unknown parameter for parport%d ignored.", context, idx));
2774 } else if ((!strncmp(params[0], "usb", 3)) && (strlen(params[0]) == 4)) {
2775 char tmpname[80];
2776 idx = params[0][3];
2777 if ((idx < '1') || (idx > '9')) {
2778 PARSE_ERR(("%s: usbX directive malformed.", context));
2780 idx -= '0';
2781 if (idx > BX_N_USB_HUBS) {
2782 PARSE_ERR(("%s: usbX hub number out of range.", context));
2784 sprintf(tmpname, "ports.usb.%d", idx);
2785 base = (bx_list_c*) SIM->get_param(tmpname);
2786 for (i=1; i<num_params; i++) {
2787 if (!strncmp(params[i], "enabled=", 8)) {
2788 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2789 } else if (!strncmp(params[i], "port1=", 6)) {
2790 SIM->get_param_string("port1", base)->set(&params[i][6]);
2791 } else if (!strncmp(params[i], "option1=", 8)) {
2792 PARSE_WARN(("%s: usb port1 option is now deprecated", context));
2793 } else if (!strncmp(params[i], "port2=", 6)) {
2794 SIM->get_param_string("port2", base)->set(&params[i][6]);
2795 } else if (!strncmp(params[i], "option2=", 8)) {
2796 PARSE_WARN(("%s: usb port2 option is now deprecated", context));
2797 } else if (!strncmp(params[i], "ioaddr=", 7)) {
2798 PARSE_WARN(("%s: usb ioaddr is now DEPRECATED (assigned by BIOS).", context));
2799 } else if (!strncmp(params[i], "irq=", 4)) {
2800 PARSE_WARN(("%s: usb irq is now DEPRECATED (assigned by BIOS).", context));
2801 } else {
2802 PARSE_WARN(("%s: unknown parameter '%s' for usb%d ignored.", context, params[i], idx));
2805 } else if (!strcmp(params[0], "i440fxsupport")) {
2806 char tmpdev[80];
2807 for (i=1; i<num_params; i++) {
2808 if (!strncmp(params[i], "enabled=", 8)) {
2809 SIM->get_param_bool(BXPN_I440FX_SUPPORT)->set(atol(&params[i][8]));
2810 } else if ((!strncmp(params[i], "slot", 4)) && (params[i][5] == '=')) {
2811 slot = atol(&params[i][4]);
2812 if ((slot > 0) && (slot < 6)) {
2813 sprintf(tmpdev, "pci.slot.%d", slot);
2814 SIM->get_param_string(tmpdev)->set(&params[i][6]);
2815 } else {
2816 BX_ERROR(("%s: unknown pci slot number ignored.", context));
2818 } else {
2819 PARSE_ERR(("%s: i440fxsupport: unknown parameter '%s'.", context, params[i]));
2822 } else if (!strcmp(params[0], "pcidev")) {
2823 if (num_params != 3) {
2824 PARSE_ERR(("%s: pcidev directive malformed.", context));
2826 for (i=1; i<num_params; i++) {
2827 if (!strncmp(params[i], "vendor=", 7)) {
2828 if ((params[i][7] == '0') && (toupper(params[i][8]) == 'X'))
2829 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(&params[i][7], NULL, 16));
2830 else
2831 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(&params[i][7], NULL, 10));
2833 else if (!strncmp(params[i], "device=", 7)) {
2834 if ((params[i][7] == '0') && (toupper(params[i][8]) == 'X'))
2835 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(&params[i][7], NULL, 16));
2836 else
2837 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(&params[i][7], NULL, 10));
2839 else {
2840 BX_ERROR(("%s: unknown parameter for pcidev ignored.", context));
2843 } else if (!strcmp(params[0], "cmosimage")) {
2844 for (i=1; i<num_params; i++) {
2845 if (!strncmp(params[i], "file=", 5)) {
2846 SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(&params[i][5]);
2847 } else if (!strcmp(params[i], "rtc_init=time0")) {
2848 SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(0);
2849 } else if (!strcmp(params[i], "rtc_init=image")) {
2850 SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(1);
2851 } else {
2852 // for backward compatiblity
2853 SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(params[i]);
2856 if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) {
2857 SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->set(1);
2859 } else if (!strcmp(params[0], "clock")) {
2860 for (i=1; i<num_params; i++) {
2861 if (!strncmp(params[i], "sync=", 5)) {
2862 SIM->get_param_enum(BXPN_CLOCK_SYNC)->set_by_name(&params[i][5]);
2864 else if (!strcmp(params[i], "time0=local")) {
2865 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_LOCAL);
2867 else if (!strcmp(params[i], "time0=utc")) {
2868 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_UTC);
2870 else if (!strncmp(params[i], "time0=", 6)) {
2871 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(atoi(&params[i][6]));
2873 else {
2874 BX_ERROR(("%s: unknown parameter for clock ignored.", context));
2878 else if (!strcmp(params[0], "gdbstub")) {
2879 #if BX_GDBSTUB
2880 if (num_params < 2) {
2881 PARSE_ERR(("%s: gdbstub directive: wrong # args.", context));
2883 base = (bx_list_c*) SIM->get_param(BXPN_GDBSTUB);
2884 for (i=1; i<num_params; i++) {
2885 if (!strncmp(params[i], "enabled=", 8)) {
2886 if (params[i][8] == '0') {
2887 SIM->get_param_bool("enabled", base)->set(0);
2888 BX_INFO(("Disabled gdbstub"));
2889 bx_dbg.gdbstub_enabled = 0;
2891 else if (params[i][8] == '1') {
2892 SIM->get_param_bool("enabled", base)->set(1);
2893 BX_INFO(("Enabled gdbstub"));
2894 bx_dbg.gdbstub_enabled = 1;
2896 else {
2897 PARSE_ERR(("%s: gdbstub directive malformed.", context));
2900 else if (!strncmp(params[i], "port=", 5)) {
2901 SIM->get_param_num("port", base)->set(atoi(&params[i][5]));
2903 else if (!strncmp(params[i], "text_base=", 10)) {
2904 SIM->get_param_num("text_base", base)->set(atoi(&params[i][10]));
2906 else if (!strncmp(params[i], "data_base=", 10)) {
2907 SIM->get_param_num("data_base", base)->set(atoi(&params[i][10]));
2909 else if (!strncmp(params[i], "bss_base=", 9)) {
2910 SIM->get_param_num("bss_base", base)->set(atoi(&params[i][9]));
2912 else {
2913 PARSE_ERR(("%s: gdbstub directive malformed.", context));
2916 #else
2917 PARSE_ERR(("%s: Bochs is not compiled with gdbstub support", context));
2918 #endif
2920 else if (!strcmp(params[0], "magic_break")) {
2921 #if BX_DEBUGGER
2922 if (num_params != 2) {
2923 PARSE_ERR(("%s: magic_break directive: wrong # args.", context));
2925 if (strncmp(params[1], "enabled=", 8)) {
2926 PARSE_ERR(("%s: magic_break directive malformed.", context));
2928 if (params[1][8] == '0') {
2929 BX_INFO(("Ignoring magic break points"));
2930 bx_dbg.magic_break_enabled = 0;
2932 else if (params[1][8] == '1') {
2933 BX_INFO(("Stopping on magic break points"));
2934 bx_dbg.magic_break_enabled = 1;
2936 else {
2937 PARSE_ERR(("%s: magic_break directive malformed.", context));
2939 #else
2940 PARSE_ERR(("%s: Bochs is not compiled with internal debugger support", context));
2941 #endif
2943 else if (!strcmp(params[0], "debug_symbols")) {
2944 if (parse_debug_symbols(context, params + 1, num_params - 1) < 0) {
2945 return -1;
2948 else if (!strcmp(params[0], "print_timestamps")) {
2949 if (num_params != 2) {
2950 PARSE_ERR(("%s: print_timestamps directive: wrong # args.", context));
2952 if (strncmp(params[1], "enabled=", 8)) {
2953 PARSE_ERR(("%s: print_timestamps directive malformed.", context));
2955 if (params[1][8] == '0' || params[1][8] == '1') {
2956 bx_dbg.print_timestamps = params[1][8] - '0';
2958 else {
2959 PARSE_ERR(("%s: print_timestamps directive malformed.", context));
2962 else if (!strcmp(params[0], "ne2k")) {
2963 int tmp[6];
2964 char tmpchar[6];
2965 int valid = 0;
2966 int n;
2967 base = (bx_list_c*) SIM->get_param(BXPN_NE2K);
2968 if (!SIM->get_param_bool("enabled", base)->get()) {
2969 SIM->get_param_enum("ethmod", base)->set_by_name("null");
2971 for (i=1; i<num_params; i++) {
2972 if (!strncmp(params[i], "enabled=", 8)) {
2973 if (atol(&params[i][8]) == 0) valid |= 0x80;
2975 else if (!strncmp(params[i], "ioaddr=", 7)) {
2976 SIM->get_param_num("ioaddr", base)->set(strtoul(&params[i][7], NULL, 16));
2977 valid |= 0x01;
2979 else if (!strncmp(params[i], "irq=", 4)) {
2980 SIM->get_param_num("irq", base)->set(atol(&params[i][4]));
2981 valid |= 0x02;
2983 else if (!strncmp(params[i], "mac=", 4)) {
2984 n = sscanf(&params[i][4], "%x:%x:%x:%x:%x:%x",
2985 &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
2986 if (n != 6) {
2987 PARSE_ERR(("%s: ne2k mac address malformed.", context));
2989 for (n=0;n<6;n++)
2990 tmpchar[n] = (unsigned char)tmp[n];
2991 SIM->get_param_string("macaddr", base)->set(tmpchar);
2992 valid |= 0x04;
2994 else if (!strncmp(params[i], "ethmod=", 7)) {
2995 if (!SIM->get_param_enum("ethmod", base)->set_by_name(&params[i][7]))
2996 PARSE_ERR(("%s: ethernet module '%s' not available", context, &params[i][7]));
2998 else if (!strncmp(params[i], "ethdev=", 7)) {
2999 SIM->get_param_string("ethdev", base)->set(&params[i][7]);
3001 else if (!strncmp(params[i], "script=", 7)) {
3002 SIM->get_param_string("script", base)->set(&params[i][7]);
3004 else {
3005 PARSE_WARN(("%s: unknown parameter '%s' for ne2k ignored.", context, params[i]));
3008 if (!SIM->get_param_bool("enabled", base)->get()) {
3009 if (valid == 0x07) {
3010 SIM->get_param_bool("enabled", base)->set(1);
3011 } else if (valid < 0x80) {
3012 PARSE_ERR(("%s: ne2k directive incomplete (ioaddr, irq and mac are required)", context));
3014 } else {
3015 if (valid & 0x80) {
3016 SIM->get_param_bool("enabled", base)->set(0);
3019 } else if (!strcmp(params[0], "pnic")) {
3020 int tmp[6];
3021 char tmpchar[6];
3022 int valid = 0;
3023 int n;
3024 base = (bx_list_c*) SIM->get_param(BXPN_PNIC);
3025 if (!SIM->get_param_bool("enabled", base)->get()) {
3026 SIM->get_param_enum("ethmod", base)->set_by_name("null");
3028 for (i=1; i<num_params; i++) {
3029 if (!strncmp(params[i], "enabled=", 8)) {
3030 if (atol(&params[i][8]) == 0) valid |= 0x80;
3031 } else if (!strncmp(params[i], "ioaddr=", 7)) {
3032 PARSE_WARN(("%s: pnic ioaddr is now DEPRECATED (assigned by BIOS).", context));
3033 } else if (!strncmp(params[i], "irq=", 4)) {
3034 PARSE_WARN(("%s: pnic irq is now DEPRECATED (assigned by BIOS).", context));
3035 } else if (!strncmp(params[i], "mac=", 4)) {
3036 n = sscanf(&params[i][4], "%x:%x:%x:%x:%x:%x",
3037 &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
3038 if (n != 6) {
3039 PARSE_ERR(("%s: pnic mac address malformed.", context));
3041 for (n=0;n<6;n++)
3042 tmpchar[n] = (unsigned char)tmp[n];
3043 SIM->get_param_string("macaddr", base)->set(tmpchar);
3044 valid |= 0x07;
3045 } else if (!strncmp(params[i], "ethmod=", 7)) {
3046 if (!SIM->get_param_enum("ethmod", base)->set_by_name(&params[i][7]))
3047 PARSE_ERR(("%s: ethernet module '%s' not available", context, &params[i][7]));
3048 } else if (!strncmp(params[i], "ethdev=", 7)) {
3049 SIM->get_param_string("ethdev", base)->set(&params[i][7]);
3050 } else if (!strncmp(params[i], "script=", 7)) {
3051 SIM->get_param_string("script", base)->set(&params[i][7]);
3052 } else {
3053 PARSE_WARN(("%s: unknown parameter '%s' for pnic ignored.", context, params[i]));
3056 if (!SIM->get_param_bool("enabled", base)->get()) {
3057 if (valid == 0x07) {
3058 SIM->get_param_bool("enabled", base)->set(1);
3059 } else if (valid < 0x80) {
3060 PARSE_ERR(("%s: pnic directive incomplete (mac is required)", context));
3062 } else {
3063 if (valid & 0x80) {
3064 SIM->get_param_bool("enabled", base)->set(0);
3067 } else if (!strcmp(params[0], "load32bitOSImage")) {
3068 if ((num_params!=4) && (num_params!=5)) {
3069 PARSE_ERR(("%s: load32bitOSImage directive: wrong # args.", context));
3071 if (strncmp(params[1], "os=", 3)) {
3072 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
3074 if (!strcmp(&params[1][3], "nullkernel")) {
3075 SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSNullKernel);
3077 else if (!strcmp(&params[1][3], "linux")) {
3078 SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSLinux);
3080 else {
3081 PARSE_ERR(("%s: load32bitOSImage: unsupported OS.", context));
3083 if (strncmp(params[2], "path=", 5)) {
3084 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
3086 if (strncmp(params[3], "iolog=", 6)) {
3087 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
3089 SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->set(&params[2][5]);
3090 SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->set(&params[3][6]);
3091 if (num_params == 5) {
3092 if (strncmp(params[4], "initrd=", 7)) {
3093 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
3095 SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->set(&params[4][7]);
3098 else if (!strcmp(params[0], "keyboard_type")) {
3099 if (num_params != 2) {
3100 PARSE_ERR(("%s: keyboard_type directive: wrong # args.", context));
3102 if (!SIM->get_param_enum(BXPN_KBD_TYPE)->set_by_name(params[1])) {
3103 PARSE_ERR(("%s: keyboard_type directive: wrong arg '%s'.", context,params[1]));
3106 else if (!strcmp(params[0], "keyboard_mapping")
3107 ||!strcmp(params[0], "keyboardmapping")) {
3108 for (i=1; i<num_params; i++) {
3109 if (!strncmp(params[i], "enabled=", 8)) {
3110 SIM->get_param_bool(BXPN_KBD_USEMAPPING)->set(atol(&params[i][8]));
3112 else if (!strncmp(params[i], "map=", 4)) {
3113 SIM->get_param_string(BXPN_KBD_KEYMAP)->set(&params[i][4]);
3117 else if (!strcmp(params[0], "user_shortcut"))
3119 if (num_params != 2) {
3120 PARSE_ERR(("%s: user_shortcut directive: wrong # args.", context));
3122 if(!strncmp(params[1], "keys=", 4)) {
3123 SIM->get_param_string(BXPN_USER_SHORTCUT)->set(&params[1][5]);
3124 if ((strchr(&params[1][5], '-') == NULL) && (strlen(&params[1][5]) > 5))
3125 PARSE_WARN(("user_shortcut: old-style syntax detected"));
3126 } else {
3127 PARSE_ERR(("%s: user_shortcut directive malformed.", context));
3130 else if (!strcmp(params[0], "config_interface"))
3132 if (num_params != 2) {
3133 PARSE_ERR(("%s: config_interface directive: wrong # args.", context));
3135 if (!SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->set_by_name(params[1]))
3136 PARSE_ERR(("%s: config_interface '%s' not available", context, params[1]));
3138 else if (!strcmp(params[0], "display_library")) {
3139 if ((num_params < 2) || (num_params > 3)) {
3140 PARSE_ERR(("%s: display_library directive: wrong # args.", context));
3142 if (!SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->set_by_name(params[1]))
3143 PARSE_ERR(("%s: display library '%s' not available", context, params[1]));
3144 if (num_params == 3) {
3145 if (!strncmp(params[2], "options=", 8)) {
3146 SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->set(&params[2][8]);
3150 // user-defined options handled by registered functions
3151 else if ((i = SIM->find_user_option(params[0])) >= 0)
3153 return SIM->parse_user_option(i, context, num_params, &params[0]);
3155 else
3157 PARSE_ERR(("%s: directive '%s' not understood", context, params[0]));
3159 return 0;
3163 static const char *fdtypes[] = {
3164 "none", "1_2", "1_44", "2_88", "720k", "360k", "160k", "180k", "320k"
3167 int bx_write_floppy_options(FILE *fp, int drive)
3169 char path[80], type[80], status[80];
3171 BX_ASSERT(drive==0 || drive==1);
3172 sprintf(path, "floppy.%d.path", drive);
3173 sprintf(type, "floppy.%d.type", drive);
3174 sprintf(status, "floppy.%d.status", drive);
3175 if (SIM->get_param_enum(type)->get() == BX_FLOPPY_NONE) {
3176 fprintf(fp, "# no floppy%c\n", (char)'a'+drive);
3177 return 0;
3179 BX_ASSERT(SIM->get_param_enum(type)->get() > BX_FLOPPY_NONE &&
3180 SIM->get_param_enum(type)->get() <= BX_FLOPPY_LAST);
3181 fprintf(fp, "floppy%c: %s=\"%s\", status=%s\n",
3182 (char)'a'+drive,
3183 fdtypes[SIM->get_param_enum(type)->get() - BX_FLOPPY_NONE],
3184 SIM->get_param_string(path)->getptr(),
3185 SIM->get_param_enum(status)->get_selected());
3186 return 0;
3189 int bx_write_ata_options(FILE *fp, Bit8u channel, bx_list_c *base)
3191 fprintf(fp, "ata%d: enabled=%d", channel, SIM->get_param_bool("enabled", base)->get());
3193 if (SIM->get_param_bool("enabled", base)->get()) {
3194 fprintf(fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", SIM->get_param_num("ioaddr1", base)->get(),
3195 SIM->get_param_num("ioaddr2", base)->get(), SIM->get_param_num("irq", base)->get());
3198 fprintf(fp, "\n");
3199 return 0;
3202 int bx_write_atadevice_options(FILE *fp, Bit8u channel, Bit8u drive, bx_list_c *base)
3204 if (SIM->get_param_bool("present", base)->get()) {
3205 fprintf(fp, "ata%d-%s: ", channel, drive==0?"master":"slave");
3207 if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) {
3208 fprintf(fp, "type=disk");
3210 fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected());
3211 fprintf(fp, ", translation=%s", SIM->get_param_enum("translation", base)->get_selected());
3212 fprintf(fp, ", path=\"%s\", cylinders=%d, heads=%d, spt=%d",
3213 SIM->get_param_string("path", base)->getptr(),
3214 SIM->get_param_num("cylinders", base)->get(),
3215 SIM->get_param_num("heads", base)->get(),
3216 SIM->get_param_num("spt", base)->get());
3218 if (SIM->get_param_string("journal", base)->getptr() != NULL)
3219 if (strcmp(SIM->get_param_string("journal", base)->getptr(), "") != 0)
3220 fprintf(fp, ", journal=\"%s\"", SIM->get_param_string("journal", base)->getptr());
3222 } else if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_CDROM) {
3223 fprintf(fp, "type=cdrom, path=\"%s\", status=%s",
3224 SIM->get_param_string("path", base)->getptr(),
3225 SIM->get_param_enum("status", base)->get_selected());
3228 fprintf(fp, ", biosdetect=%s", SIM->get_param_enum("biosdetect", base)->get_selected());
3230 if (SIM->get_param_string("model", base)->getptr()>0) {
3231 fprintf(fp, ", model=\"%s\"", SIM->get_param_string("model", base)->getptr());
3234 fprintf(fp, "\n");
3236 return 0;
3239 int bx_write_parport_options(FILE *fp, bx_list_c *base, int n)
3241 fprintf(fp, "parport%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3242 if (SIM->get_param_bool("enabled", base)->get()) {
3243 fprintf(fp, ", file=\"%s\"", SIM->get_param_string("outfile", base)->getptr());
3245 fprintf(fp, "\n");
3246 return 0;
3249 int bx_write_serial_options(FILE *fp, bx_list_c *base, int n)
3251 fprintf(fp, "com%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3252 if (SIM->get_param_bool("enabled", base)->get()) {
3253 fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected());
3254 fprintf(fp, ", dev=\"%s\"", SIM->get_param_string("dev", base)->getptr());
3256 fprintf(fp, "\n");
3257 return 0;
3260 int bx_write_usb_options(FILE *fp, bx_list_c *base, int n)
3262 fprintf(fp, "usb%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3263 if (SIM->get_param_bool("enabled", base)->get()) {
3264 fprintf(fp, ", port1=%s", SIM->get_param_string("port1", base)->getptr());
3265 fprintf(fp, ", port2=%s", SIM->get_param_string("port2", base)->getptr());
3267 fprintf(fp, "\n");
3268 return 0;
3271 int bx_write_pnic_options(FILE *fp, bx_list_c *base)
3273 fprintf (fp, "pnic: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3274 if (SIM->get_param_bool("enabled", base)->get()) {
3275 char *ptr = SIM->get_param_string("macaddr", base)->getptr();
3276 fprintf (fp, ", mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s",
3277 (unsigned int)(0xff & ptr[0]),
3278 (unsigned int)(0xff & ptr[1]),
3279 (unsigned int)(0xff & ptr[2]),
3280 (unsigned int)(0xff & ptr[3]),
3281 (unsigned int)(0xff & ptr[4]),
3282 (unsigned int)(0xff & ptr[5]),
3283 SIM->get_param_enum("ethmod", base)->get_selected(),
3284 SIM->get_param_string("ethdev", base)->getptr(),
3285 SIM->get_param_string("script", base)->getptr());
3287 fprintf (fp, "\n");
3288 return 0;
3291 int bx_write_ne2k_options (FILE *fp, bx_list_c *base)
3293 fprintf(fp, "ne2k: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3294 if (SIM->get_param_bool("enabled", base)->get()) {
3295 char *ptr = SIM->get_param_string("macaddr", base)->getptr();
3296 fprintf(fp, ", ioaddr=0x%x, irq=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s",
3297 SIM->get_param_num("ioaddr", base)->get(),
3298 SIM->get_param_num("irq", base)->get(),
3299 (unsigned int)(0xff & ptr[0]),
3300 (unsigned int)(0xff & ptr[1]),
3301 (unsigned int)(0xff & ptr[2]),
3302 (unsigned int)(0xff & ptr[3]),
3303 (unsigned int)(0xff & ptr[4]),
3304 (unsigned int)(0xff & ptr[5]),
3305 SIM->get_param_enum("ethmod", base)->get_selected(),
3306 SIM->get_param_string("ethdev", base)->getptr(),
3307 SIM->get_param_string("script", base)->getptr());
3309 fprintf(fp, "\n");
3310 return 0;
3313 int bx_write_sb16_options (FILE *fp, bx_list_c *base)
3315 fprintf(fp, "sb16: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3316 if (SIM->get_param_bool("enabled", base)->get()) {
3317 fprintf(fp, ", midimode=%d, midi=%s, wavemode=%d, wave=%s, loglevel=%d, log=%s, dmatimer=%d",
3318 SIM->get_param_num("midimode", base)->get(),
3319 SIM->get_param_string("midifile", base)->getptr(),
3320 SIM->get_param_num("wavemode", base)->get(),
3321 SIM->get_param_string("wavefile", base)->getptr(),
3322 SIM->get_param_num("loglevel", base)->get(),
3323 SIM->get_param_string("logfile", base)->getptr(),
3324 SIM->get_param_num("dmatimer", base)->get());
3326 fprintf(fp, "\n");
3327 return 0;
3330 int bx_write_loader_options(FILE *fp)
3332 if (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNone) {
3333 fprintf(fp, "# no loader\n");
3334 return 0;
3336 BX_ASSERT((SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ||
3337 (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNullKernel));
3338 fprintf (fp, "load32bitOSImage: os=%s, path=%s, iolog=%s, initrd=%s\n",
3339 (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ? "linux" : "nullkernel",
3340 SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(),
3341 SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr(),
3342 SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->getptr());
3343 return 0;
3346 int bx_write_clock_cmos_options(FILE *fp)
3348 fprintf(fp, "clock: ");
3350 switch (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()) {
3351 case BX_CLOCK_SYNC_NONE:
3352 fprintf(fp, "sync=none");
3353 break;
3354 case BX_CLOCK_SYNC_REALTIME:
3355 fprintf(fp, "sync=realtime");
3356 break;
3357 case BX_CLOCK_SYNC_SLOWDOWN:
3358 fprintf(fp, "sync=slowdown");
3359 break;
3360 case BX_CLOCK_SYNC_BOTH:
3361 fprintf(fp, "sync=both");
3362 break;
3363 default:
3364 BX_PANIC(("Unknown value for sync method"));
3367 switch (SIM->get_param_num(BXPN_CLOCK_TIME0)->get()) {
3368 case 0: break;
3369 case BX_CLOCK_TIME0_LOCAL:
3370 fprintf(fp, ", time0=local");
3371 break;
3372 case BX_CLOCK_TIME0_UTC:
3373 fprintf(fp, ", time0=utc");
3374 break;
3375 default:
3376 fprintf(fp, ", time0=%u", SIM->get_param_num(BXPN_CLOCK_TIME0)->get());
3379 fprintf(fp, "\n");
3381 if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) {
3382 fprintf(fp, "cmosimage: file=%s, ", SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr());
3383 fprintf(fp, "rtc_init=%s\n", SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->get()?"image":"time0");
3384 } else {
3385 fprintf(fp, "# no cmosimage\n");
3387 return 0;
3390 int bx_write_log_options(FILE *fp, bx_list_c *base)
3392 fprintf(fp, "log: %s\n", SIM->get_param_string("filename", base)->getptr());
3393 fprintf(fp, "logprefix: %s\n", SIM->get_param_string("prefix", base)->getptr());
3394 #if BX_DEBUGGER
3395 fprintf(fp, "debugger_log: %s\n", SIM->get_param_string("debugger_filename", base)->getptr());
3396 #endif
3397 fprintf(fp, "panic: action=%s\n",
3398 io->getaction(logfunctions::get_default_action(LOGLEV_PANIC)));
3399 fprintf(fp, "error: action=%s\n",
3400 io->getaction(logfunctions::get_default_action(LOGLEV_ERROR)));
3401 fprintf(fp, "info: action=%s\n",
3402 io->getaction(logfunctions::get_default_action(LOGLEV_INFO)));
3403 fprintf(fp, "debug: action=%s\n",
3404 io->getaction(logfunctions::get_default_action(LOGLEV_DEBUG)));
3405 fprintf(fp, "pass: action=%s\n",
3406 io->getaction(logfunctions::get_default_action(LOGLEV_PASS)));
3407 return 0;
3410 int bx_write_keyboard_options(FILE *fp)
3412 fprintf(fp, "keyboard_type: %s\n", SIM->get_param_enum(BXPN_KBD_TYPE)->get_selected());
3413 fprintf(fp, "keyboard_serial_delay: %u\n", SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get());
3414 fprintf(fp, "keyboard_paste_delay: %u\n", SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get());
3415 fprintf(fp, "keyboard_mapping: enabled=%d, map=%s\n",
3416 SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get(),
3417 SIM->get_param_string(BXPN_KBD_KEYMAP)->getptr());
3418 fprintf(fp, "user_shortcut: keys=%s\n", SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr());
3419 return 0;
3422 // return values:
3423 // 0: written ok
3424 // -1: failed
3425 // -2: already exists, and overwrite was off
3426 int bx_write_configuration(const char *rc, int overwrite)
3428 int i;
3429 char *strptr, tmppath[80], tmpaddr[80], tmpdev[80];
3430 bx_list_c *base;
3431 BX_INFO(("write current configuration to %s", rc));
3432 // check if it exists. If so, only proceed if overwrite is set.
3433 FILE *fp = fopen(rc, "r");
3434 if (fp != NULL) {
3435 fclose(fp);
3436 if (!overwrite) return -2;
3438 fp = fopen(rc, "w");
3439 if (fp == NULL) return -1;
3440 // finally it's open and we can start writing.
3441 fprintf(fp, "# configuration file generated by Bochs\n");
3442 fprintf(fp, "config_interface: %s\n", SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->get_selected());
3443 fprintf(fp, "display_library: %s", SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->get_selected());
3444 strptr = SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr();
3445 if (strlen(strptr) > 0)
3446 fprintf(fp, ", options=\"%s\"\n", strptr);
3447 else
3448 fprintf(fp, "\n");
3449 fprintf(fp, "megs: %d\n", SIM->get_param_num(BXPN_MEM_SIZE)->get());
3450 strptr = SIM->get_param_string(BXPN_ROM_PATH)->getptr();
3451 if (strlen(strptr) > 0) {
3452 fprintf(fp, "romimage: file=\"%s\"", strptr);
3453 if (SIM->get_param_num(BXPN_ROM_ADDRESS)->get() != 0)
3454 fprintf(fp, ", address=0x%08x\n", (unsigned int) SIM->get_param_num(BXPN_ROM_ADDRESS)->get());
3455 else
3456 fprintf(fp, "\n");
3458 else {
3459 fprintf(fp, "# no romimage\n");
3461 strptr = SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr();
3462 if (strlen(strptr) > 0)
3463 fprintf(fp, "vgaromimage: file=\"%s\"\n", strptr);
3464 else
3465 fprintf(fp, "# no vgaromimage\n");
3466 fprintf(fp, "boot: %s", SIM->get_param_enum(BXPN_BOOTDRIVE1)->get_selected());
3467 for (i=1; i<3; i++) {
3468 sprintf(tmppath, "boot_params.boot_drive%d", i+1);
3469 if (SIM->get_param_enum(tmppath)->get() != BX_BOOT_NONE) {
3470 fprintf(fp, ", %s", SIM->get_param_enum(tmppath)->get_selected());
3473 fprintf(fp, "\n");
3474 fprintf(fp, "floppy_bootsig_check: disabled=%d\n", SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->get());
3475 // it would be nice to put this type of function as methods on
3476 // the structs like bx_floppy_options::print or something.
3477 bx_write_floppy_options(fp, 0);
3478 bx_write_floppy_options(fp, 1);
3479 for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
3480 sprintf(tmppath, "ata.%d", channel);
3481 base = (bx_list_c*) SIM->get_param(tmppath);
3482 bx_write_ata_options(fp, channel, (bx_list_c*) SIM->get_param("resources", base));
3483 bx_write_atadevice_options(fp, channel, 0, (bx_list_c*) SIM->get_param("master", base));
3484 bx_write_atadevice_options(fp, channel, 1, (bx_list_c*) SIM->get_param("slave", base));
3486 for (i=0; i<BX_N_OPTROM_IMAGES; i++) {
3487 sprintf(tmppath, "memory.optrom.%d.path", i+1);
3488 sprintf(tmpaddr, "memory.optrom.%d.addr", i+1);
3489 strptr = SIM->get_param_string(tmppath)->getptr();
3490 if (strlen(strptr) > 0)
3491 fprintf(fp, "optromimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr,
3492 (unsigned int)SIM->get_param_num(tmpaddr)->get());
3494 for (i=0; i<BX_N_OPTRAM_IMAGES; i++) {
3495 sprintf(tmppath, "memory.optram.%d.path", i+1);
3496 sprintf(tmpaddr, "memory.optram.%d.addr", i+1);
3497 strptr = SIM->get_param_string(tmppath)->getptr();
3498 if (strlen(strptr) > 0)
3499 fprintf(fp, "optramimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr,
3500 (unsigned int)SIM->get_param_num(tmpaddr)->get());
3502 // parallel ports
3503 for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
3504 sprintf(tmpdev, "ports.parallel.%d", i+1);
3505 base = (bx_list_c*) SIM->get_param(tmpdev);
3506 bx_write_parport_options(fp, base, i+1);
3508 // serial ports
3509 for (i=0; i<BX_N_SERIAL_PORTS; i++) {
3510 sprintf(tmpdev, "ports.serial.%d", i+1);
3511 base = (bx_list_c*) SIM->get_param(tmpdev);
3512 bx_write_serial_options(fp, base, i+1);
3514 base = (bx_list_c*) SIM->get_param("ports.usb.1");
3515 bx_write_usb_options(fp, base, 1);
3516 // pci
3517 fprintf(fp, "i440fxsupport: enabled=%d",
3518 SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get());
3519 if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) {
3520 for (i=0; i<BX_N_PCI_SLOTS; i++) {
3521 sprintf(tmpdev, "pci.slot.%d", i+1);
3522 strptr = SIM->get_param_string(tmpdev)->getptr();
3523 if (strlen(strptr) > 0) {
3524 fprintf(fp, ", slot%d=%s", i+1, strptr);
3528 fprintf(fp, "\n");
3529 if (SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get() != 0xffff) {
3530 fprintf(fp, "pcidev: vendor=0x%04x, device=0x%04x\n",
3531 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get(),
3532 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->get());
3534 fprintf(fp, "vga_update_interval: %u\n", SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->get());
3535 fprintf(fp, "vga: extension=%s\n", SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr());
3536 #if BX_SUPPORT_SMP
3537 fprintf(fp, "cpu: count=%u:%u:%u, ips=%u, quantum=%d, reset_on_triple_fault=%d, cpuid_limit_winnt=%d\n",
3538 SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get(), SIM->get_param_num(BXPN_CPU_NCORES)->get(),
3539 SIM->get_param_num(BXPN_CPU_NTHREADS)->get(), SIM->get_param_num(BXPN_IPS)->get(),
3540 SIM->get_param_num(BXPN_SMP_QUANTUM)->get(),
3541 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get(),
3542 SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get());
3543 #else
3544 fprintf(fp, "cpu: count=1, ips=%u, reset_on_triple_fault=%d, cpuid_limit_winnt=%d\n",
3545 SIM->get_param_num(BXPN_IPS)->get(),
3546 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get(),
3547 SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get());
3548 #endif
3549 fprintf(fp, "text_snapshot_check: enabled=%d\n", SIM->get_param_bool(BXPN_TEXT_SNAPSHOT_CHECK)->get());
3550 fprintf(fp, "private_colormap: enabled=%d\n", SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get());
3551 #if BX_WITH_AMIGAOS
3552 fprintf(fp, "fullscreen: enabled=%d\n", SIM->get_param_bool(BXPN_FULLSCREEN)->get());
3553 fprintf(fp, "screenmode: name=\"%s\"\n", SIM->get_param_string(BXPN_SCREENMODE)->getptr());
3554 #endif
3555 bx_write_clock_cmos_options(fp);
3556 bx_write_ne2k_options(fp, (bx_list_c*) SIM->get_param(BXPN_NE2K));
3557 bx_write_pnic_options(fp, (bx_list_c*) SIM->get_param(BXPN_PNIC));
3558 bx_write_sb16_options(fp, (bx_list_c*) SIM->get_param(BXPN_SB16));
3559 bx_write_loader_options(fp);
3560 bx_write_log_options(fp, (bx_list_c*) SIM->get_param("log"));
3561 bx_write_keyboard_options(fp);
3562 fprintf(fp, "mouse: enabled=%d, type=%s\n",
3563 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get(),
3564 SIM->get_param_enum(BXPN_MOUSE_TYPE)->get_selected());
3565 SIM->save_user_options(fp);
3566 fclose(fp);
3567 return 0;
3570 #endif // #if BX_PROVIDE_MAIN