/[gxemul]/trunk/src/emul_parse.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/emul_parse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 22556 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: emul_parse.c,v 1.32 2005/06/24 09:33:34 debug Exp $
29 *
30 * Set up an emulation by parsing a config file.
31 *
32 * TODO: This could be extended to support XML config files as well, but
33 * XML is ugly. It is ugly right now as well. The question is: which
34 * solution is the least ugly?
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "diskimage.h"
42 #include "emul.h"
43 #include "machine.h"
44 #include "misc.h"
45 #include "net.h"
46
47
48 #define is_word_char(ch) ( \
49 (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || \
50 ch == '_' || ch == '$' || (ch >= '0' && ch <= '9') )
51
52
53 #define EXPECT_WORD 1
54 #define EXPECT_LEFT_PARENTHESIS 2
55 #define EXPECT_RIGHT_PARENTHESIS 4
56
57
58 /*
59 * read_one_word():
60 *
61 * Reads the file f until it has read a complete word. Whitespace is ignored,
62 * and also any exclamation mark ('!') and anything following an exclamation
63 * mark on a line.
64 *
65 * Used internally by emul_parse_config().
66 */
67 static void read_one_word(FILE *f, char *buf, int buflen, int *line,
68 int expect)
69 {
70 int ch;
71 int done = 0;
72 int curlen = 0;
73 int in_word = 0;
74
75 while (!done) {
76 if (curlen >= buflen - 1)
77 break;
78
79 ch = fgetc(f);
80 if (ch == EOF)
81 break;
82
83 if (in_word) {
84 if (is_word_char(ch)) {
85 buf[curlen++] = ch;
86 if (curlen == buflen - 1)
87 done = 1;
88 continue;
89 } else {
90 if (ungetc(ch, f) == EOF) {
91 fatal("ungetc() failed?\n");
92 exit(1);
93 }
94 break;
95 }
96 }
97
98 if (ch == '\n') {
99 (*line) ++;
100 continue;
101 }
102
103 if (ch == '\r')
104 continue;
105
106 if (ch == '!') {
107 /* Skip until newline: */
108 while (ch != '\n' && ch != EOF)
109 ch = fgetc(f);
110 if (ch == '\n')
111 (*line) ++;
112 continue;
113 }
114
115 if (ch == '{') {
116 int depth = 1;
117
118 /* Skip until '}': */
119 while (depth > 0) {
120 ch = fgetc(f);
121 if (ch == '\n')
122 (*line) ++;
123 if (ch == '{')
124 depth ++;
125 if (ch == '}')
126 depth --;
127 if (ch == EOF) {
128 fatal("line %i: unexpected EOF inside"
129 " a nested comment\n", *line);
130 exit(1);
131 }
132 }
133 continue;
134 }
135
136 /* Whitespace? */
137 if (ch <= ' ')
138 continue;
139
140 if (ch == '"' || ch == '\'') {
141 /* This is a quoted word. */
142 int start_ch = ch;
143
144 if (expect & EXPECT_LEFT_PARENTHESIS) {
145 fatal("unexpected character '%c', line %i\n",
146 ch, *line);
147 exit(1);
148 }
149
150 while (curlen < buflen - 1) {
151 ch = fgetc(f);
152 if (ch == '\n') {
153 fatal("line %i: newline inside"
154 " quotes?\n", *line);
155 exit(1);
156 }
157 if (ch == EOF) {
158 fatal("line %i: EOF inside a quoted"
159 " string?\n", *line);
160 exit(1);
161 }
162 if (ch == start_ch)
163 break;
164 buf[curlen++] = ch;
165 }
166 break;
167 }
168
169 if ((expect & EXPECT_WORD) && is_word_char(ch)) {
170 buf[curlen++] = ch;
171 in_word = 1;
172 if (curlen == buflen - 1)
173 done = 1;
174 } else {
175 if ((expect & EXPECT_LEFT_PARENTHESIS) && ch == '(') {
176 buf[curlen++] = ch;
177 break;
178 }
179 if ((expect & EXPECT_RIGHT_PARENTHESIS) && ch == ')') {
180 buf[curlen++] = ch;
181 break;
182 }
183
184 fatal("unexpected character '%c', line %i\n",
185 ch, *line);
186 exit(1);
187 }
188 }
189
190 buf[curlen] = '\0';
191 }
192
193
194 #define PARSESTATE_NONE 0
195 #define PARSESTATE_EMUL 1
196 #define PARSESTATE_NET 2
197 #define PARSESTATE_MACHINE 3
198
199 static char cur_net_ipv4net[50];
200 static char cur_net_ipv4len[50];
201 static char cur_net_local_port[10];
202 #define MAX_N_REMOTE 20
203 #define MAX_REMOTE_LEN 100
204 static char *cur_net_remote[MAX_N_REMOTE];
205 static int cur_net_n_remote;
206
207 static char cur_machine_name[50];
208 static char cur_machine_cpu[50];
209 static char cur_machine_type[50];
210 static char cur_machine_subtype[50];
211 static char cur_machine_bootname[150];
212 static char cur_machine_bootarg[250];
213 static char cur_machine_slowsi[10];
214 static char cur_machine_debugger_on_badaddr[10];
215 static char cur_machine_prom_emulation[10];
216 static char cur_machine_use_x11[10];
217 static char cur_machine_x11_scaledown[10];
218 static char cur_machine_bintrans[10];
219 static char cur_machine_old_bintrans[10];
220 static char cur_machine_bintrans_size[10];
221 static char cur_machine_byte_order[20];
222 static char cur_machine_random_mem[10];
223 static char cur_machine_random_cpu[10];
224 static char cur_machine_force_netboot[10];
225 static char cur_machine_start_paused[10];
226 static char cur_machine_ncpus[10];
227 static char cur_machine_n_gfx_cards[10];
228 static char cur_machine_serial_nr[10];
229 static char cur_machine_emulated_hz[10];
230 static char cur_machine_memory[10];
231 #define MAX_N_LOAD 15
232 #define MAX_LOAD_LEN 2000
233 static char *cur_machine_load[MAX_N_LOAD];
234 static int cur_machine_n_load;
235 #define MAX_N_DISK 10
236 #define MAX_DISK_LEN 2000
237 static char *cur_machine_disk[MAX_N_DISK];
238 static int cur_machine_n_disk;
239 #define MAX_N_DEVICE 20
240 #define MAX_DEVICE_LEN 400
241 static char *cur_machine_device[MAX_N_DISK];
242 static int cur_machine_n_device;
243 #define MAX_N_X11_DISP 5
244 #define MAX_X11_DISP_LEN 1000
245 static char *cur_machine_x11_disp[MAX_N_X11_DISP];
246 static int cur_machine_n_x11_disp;
247
248 #define WORD(w,var) { \
249 if (strcmp(word, w) == 0) { \
250 read_one_word(f, word, maxbuflen, \
251 line, EXPECT_LEFT_PARENTHESIS); \
252 read_one_word(f, var, sizeof(var), \
253 line, EXPECT_WORD); \
254 read_one_word(f, word, maxbuflen, \
255 line, EXPECT_RIGHT_PARENTHESIS); \
256 return; \
257 } \
258 }
259
260
261 /*
262 * parse_on_off():
263 *
264 * Returns 1 for "on", "yes", "enable", or "1".
265 * Returns 0 for "off", "no", "disable", or "0".
266 * Prints a fatal warning and exit()s for other values.
267 */
268 int parse_on_off(char *s)
269 {
270 if (strcasecmp(s, "on") == 0 || strcasecmp(s, "yes") == 0 ||
271 strcasecmp(s, "enable") == 0 || strcasecmp(s, "1") == 0)
272 return 1;
273 if (strcasecmp(s, "off") == 0 || strcasecmp(s, "no") == 0 ||
274 strcasecmp(s, "disable") == 0 || strcasecmp(s, "0") == 0)
275 return 0;
276
277 fatal("parse_on_off(): unknown value '%s'\n", s);
278 exit(1);
279 }
280
281
282 /*
283 * parse__none():
284 *
285 * emul ( [...] )
286 */
287 static void parse__none(struct emul *e, FILE *f, int *in_emul, int *line,
288 int *parsestate, char *word, size_t maxbuflen)
289 {
290 if (strcmp(word, "emul") == 0) {
291 if (*in_emul) {
292 fatal("line %i: only one emul per config "
293 "file is supported!\n", *line);
294 exit(1);
295 }
296 *parsestate = PARSESTATE_EMUL;
297 *in_emul = 1;
298 read_one_word(f, word, maxbuflen,
299 line, EXPECT_LEFT_PARENTHESIS);
300 return;
301 }
302
303 fatal("line %i: expecting 'emul', not '%s'\n", *line, word);
304 exit(1);
305 }
306
307
308 /*
309 * parse__emul():
310 *
311 * name, net, machine
312 */
313 static void parse__emul(struct emul *e, FILE *f, int *in_emul, int *line,
314 int *parsestate, char *word, size_t maxbuflen)
315 {
316 if (word[0] == ')') {
317 *parsestate = PARSESTATE_NONE;
318 return;
319 }
320
321 if (strcmp(word, "name") == 0) {
322 char tmp[200];
323 read_one_word(f, word, maxbuflen,
324 line, EXPECT_LEFT_PARENTHESIS);
325 read_one_word(f, tmp, sizeof(tmp), line, EXPECT_WORD);
326 read_one_word(f, word, maxbuflen,
327 line, EXPECT_RIGHT_PARENTHESIS);
328 if (e->name != NULL) {
329 free(e->name);
330 e->name = NULL;
331 }
332 e->name = strdup(tmp);
333 if (e->name == NULL) {
334 fprintf(stderr, "out of memory in parse__emul()\n");
335 exit(1);
336 }
337 debug("name: \"%s\"\n", e->name);
338 return;
339 }
340
341 if (strcmp(word, "net") == 0) {
342 *parsestate = PARSESTATE_NET;
343 read_one_word(f, word, maxbuflen,
344 line, EXPECT_LEFT_PARENTHESIS);
345
346 /* Default net: */
347 strlcpy(cur_net_ipv4net, "10.0.0.0", sizeof(cur_net_ipv4net));
348 strlcpy(cur_net_ipv4len, "8", sizeof(cur_net_ipv4len));
349 strlcpy(cur_net_local_port, "", sizeof(cur_net_local_port));
350 cur_net_n_remote = 0;
351 return;
352 }
353
354 if (strcmp(word, "machine") == 0) {
355 *parsestate = PARSESTATE_MACHINE;
356 read_one_word(f, word, maxbuflen,
357 line, EXPECT_LEFT_PARENTHESIS);
358
359 /* A "zero state": */
360 cur_machine_name[0] = '\0';
361 cur_machine_cpu[0] = '\0';
362 cur_machine_type[0] = '\0';
363 cur_machine_subtype[0] = '\0';
364 cur_machine_bootname[0] = '\0';
365 cur_machine_bootarg[0] = '\0';
366 cur_machine_n_load = 0;
367 cur_machine_n_disk = 0;
368 cur_machine_n_device = 0;
369 cur_machine_n_x11_disp = 0;
370 cur_machine_slowsi[0] = '\0';
371 cur_machine_debugger_on_badaddr[0] = '\0';
372 cur_machine_prom_emulation[0] = '\0';
373 cur_machine_use_x11[0] = '\0';
374 cur_machine_x11_scaledown[0] = '\0';
375 cur_machine_bintrans[0] = '\0';
376 cur_machine_old_bintrans[0] = '\0';
377 cur_machine_bintrans_size[0] = '\0';
378 cur_machine_byte_order[0] = '\0';
379 cur_machine_random_mem[0] = '\0';
380 cur_machine_random_cpu[0] = '\0';
381 cur_machine_force_netboot[0] = '\0';
382 cur_machine_start_paused[0] = '\0';
383 cur_machine_ncpus[0] = '\0';
384 cur_machine_n_gfx_cards[0] = '\0';
385 cur_machine_serial_nr[0] = '\0';
386 cur_machine_emulated_hz[0] = '\0';
387 cur_machine_memory[0] = '\0';
388 return;
389 }
390
391 fatal("line %i: not expecting '%s' in an 'emul' section\n",
392 *line, word);
393 exit(1);
394 }
395
396
397 /*
398 * parse__net():
399 *
400 * Simple words: ipv4net, ipv4len, local_port
401 *
402 * Complex: add_remote
403 *
404 * TODO: more words? for example an option to disable the gateway? that would
405 * have to be implemented correctly in src/net.c first.
406 */
407 static void parse__net(struct emul *e, FILE *f, int *in_emul, int *line,
408 int *parsestate, char *word, size_t maxbuflen)
409 {
410 int i;
411
412 if (word[0] == ')') {
413 /* Finished with the 'net' section. Let's create the net: */
414 if (e->net != NULL) {
415 fatal("line %i: more than one net isn't really "
416 "supported yet\n", *line);
417 exit(1);
418 }
419
420 if (!cur_net_local_port[0])
421 strlcpy(cur_net_local_port, "0",
422 sizeof(cur_net_local_port));
423
424 e->net = net_init(e, NET_INIT_FLAG_GATEWAY,
425 cur_net_ipv4net, atoi(cur_net_ipv4len),
426 cur_net_remote, cur_net_n_remote,
427 atoi(cur_net_local_port));
428
429 if (e->net == NULL) {
430 fatal("line %i: fatal error: could not create"
431 " the net (?)\n", *line);
432 exit(1);
433 }
434
435 for (i=0; i<cur_net_n_remote; i++) {
436 free(cur_net_remote[i]);
437 cur_net_remote[i] = NULL;
438 }
439
440 *parsestate = PARSESTATE_EMUL;
441 return;
442 }
443
444 WORD("ipv4net", cur_net_ipv4net);
445 WORD("ipv4len", cur_net_ipv4len);
446 WORD("local_port", cur_net_local_port);
447
448 if (strcmp(word, "add_remote") == 0) {
449 read_one_word(f, word, maxbuflen,
450 line, EXPECT_LEFT_PARENTHESIS);
451 if (cur_net_n_remote >= MAX_N_REMOTE) {
452 fprintf(stderr, "too many remote networks\n");
453 exit(1);
454 }
455 cur_net_remote[cur_net_n_remote] = malloc(MAX_REMOTE_LEN);
456 if (cur_net_remote[cur_net_n_remote] == NULL) {
457 fprintf(stderr, "out of memory\n");
458 exit(1);
459 }
460 read_one_word(f, cur_net_remote[cur_net_n_remote],
461 MAX_REMOTE_LEN, line, EXPECT_WORD);
462 cur_net_n_remote ++;
463 read_one_word(f, word, maxbuflen, line,
464 EXPECT_RIGHT_PARENTHESIS);
465 return;
466 }
467
468 fatal("line %i: not expecting '%s' in a 'net' section\n", *line, word);
469 exit(1);
470 }
471
472
473 /*
474 * parse__machine():
475 */
476 static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line,
477 int *parsestate, char *word, size_t maxbuflen)
478 {
479 int r, i;
480
481 if (word[0] == ')') {
482 /* Finished with the 'machine' section. */
483 struct machine *m;
484
485 if (!cur_machine_name[0])
486 strlcpy(cur_machine_name, "no_name",
487 sizeof(cur_machine_name));
488
489 m = emul_add_machine(e, cur_machine_name);
490
491 r = machine_name_to_type(cur_machine_type, cur_machine_subtype,
492 &m->machine_type, &m->machine_subtype, &m->arch);
493 if (!r)
494 exit(1);
495
496 if (cur_machine_cpu[0])
497 m->cpu_name = strdup(cur_machine_cpu);
498
499 if (!cur_machine_use_x11[0])
500 strlcpy(cur_machine_use_x11, "no",
501 sizeof(cur_machine_use_x11));
502 m->use_x11 = parse_on_off(cur_machine_use_x11);
503
504 if (!cur_machine_slowsi[0])
505 strlcpy(cur_machine_slowsi, "no",
506 sizeof(cur_machine_slowsi));
507 m->slow_serial_interrupts_hack_for_linux =
508 parse_on_off(cur_machine_slowsi);
509
510 if (!cur_machine_debugger_on_badaddr[0])
511 strlcpy(cur_machine_debugger_on_badaddr, "no",
512 sizeof(cur_machine_debugger_on_badaddr));
513 m->single_step_on_bad_addr =
514 parse_on_off(cur_machine_debugger_on_badaddr);
515
516 if (!cur_machine_prom_emulation[0])
517 strlcpy(cur_machine_prom_emulation, "yes",
518 sizeof(cur_machine_prom_emulation));
519 m->prom_emulation = parse_on_off(cur_machine_prom_emulation);
520
521 if (!cur_machine_random_mem[0])
522 strlcpy(cur_machine_random_mem, "no",
523 sizeof(cur_machine_random_mem));
524 m->random_mem_contents =
525 parse_on_off(cur_machine_random_mem);
526
527 if (!cur_machine_random_cpu[0])
528 strlcpy(cur_machine_random_cpu, "no",
529 sizeof(cur_machine_random_cpu));
530 m->use_random_bootstrap_cpu =
531 parse_on_off(cur_machine_random_cpu);
532
533 m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;
534 if (cur_machine_byte_order[0]) {
535 if (strncasecmp(cur_machine_byte_order, "big", 3) == 0)
536 m->byte_order_override = EMUL_BIG_ENDIAN;
537 else if (strncasecmp(cur_machine_byte_order, "little",
538 6) == 0)
539 m->byte_order_override = EMUL_LITTLE_ENDIAN;
540 else {
541 fatal("Byte order must be big-endian or"
542 " little-endian\n");
543 exit(1);
544 }
545 }
546
547 if (!cur_machine_bintrans[0])
548 strlcpy(cur_machine_bintrans, "yes",
549 sizeof(cur_machine_bintrans));
550 m->bintrans_enable = m->bintrans_enabled_from_start =
551 parse_on_off(cur_machine_bintrans);
552
553 if (!cur_machine_old_bintrans[0])
554 strlcpy(cur_machine_old_bintrans, "yes",
555 sizeof(cur_machine_old_bintrans));
556 m->old_bintrans_enable = parse_on_off(cur_machine_old_bintrans);
557
558 if (!m->bintrans_enable && m->old_bintrans_enable) {
559 fatal("cannot use old bintrans when bintrans is"
560 " disabled.\n");
561 exit(1);
562 }
563
564 /* TODO: Hm... */
565 if (m->bintrans_enable)
566 m->speed_tricks = 0;
567
568 if (cur_machine_bintrans_size[0])
569 m->bintrans_size = 1048576 *
570 atoi(cur_machine_bintrans_size);
571
572 if (!cur_machine_force_netboot[0])
573 strlcpy(cur_machine_force_netboot, "no",
574 sizeof(cur_machine_force_netboot));
575 m->force_netboot = parse_on_off(cur_machine_force_netboot);
576
577 if (!cur_machine_start_paused[0])
578 strlcpy(cur_machine_start_paused, "no",
579 sizeof(cur_machine_start_paused));
580 m->start_paused = parse_on_off(cur_machine_start_paused);
581
582 /* NOTE: Default nr of CPUs is 0: */
583 if (!cur_machine_ncpus[0])
584 strlcpy(cur_machine_ncpus, "0",
585 sizeof(cur_machine_ncpus));
586 m->ncpus = atoi(cur_machine_ncpus);
587
588 if (cur_machine_n_gfx_cards[0])
589 m->n_gfx_cards = atoi(cur_machine_n_gfx_cards);
590
591 if (cur_machine_serial_nr[0]) {
592 m->serial_nr = atoi(cur_machine_serial_nr);
593 e->next_serial_nr = m->serial_nr+1;
594 }
595
596 if (cur_machine_emulated_hz[0]) {
597 m->emulated_hz = mystrtoull(cur_machine_emulated_hz,
598 NULL, 0);
599 m->automatic_clock_adjustment = 0;
600 }
601
602 /* NOTE: Default nr of CPUs is 0: */
603 if (!cur_machine_memory[0])
604 strlcpy(cur_machine_memory, "0",
605 sizeof(cur_machine_memory));
606 m->physical_ram_in_mb = atoi(cur_machine_memory);
607
608 if (!cur_machine_x11_scaledown[0])
609 m->x11_scaledown = 1;
610 else {
611 m->x11_scaledown = atoi(cur_machine_x11_scaledown);
612 if (m->x11_scaledown < 0) {
613 fprintf(stderr, "Invalid scaledown value"
614 " (%i)\n", m->x11_scaledown);
615 exit(1);
616 }
617 }
618
619 for (i=0; i<cur_machine_n_disk; i++) {
620 diskimage_add(m, cur_machine_disk[i]);
621 free(cur_machine_disk[i]);
622 cur_machine_disk[i] = NULL;
623 }
624
625 m->boot_kernel_filename = strdup(cur_machine_bootname);
626
627 if (cur_machine_bootarg[0])
628 m->boot_string_argument = strdup(cur_machine_bootarg);
629
630 for (i=0; i<cur_machine_n_x11_disp; i++) {
631 m->x11_n_display_names ++;
632 m->x11_display_names = realloc(
633 m->x11_display_names, m->x11_n_display_names
634 * sizeof(char *));
635 if (m->x11_display_names == NULL) {
636 printf("out of memory\n");
637 exit(1);
638 }
639 m->x11_display_names[m->x11_n_display_names-1] =
640 strdup(cur_machine_x11_disp[i]);
641 if (m->x11_display_names
642 [m->x11_n_display_names-1] == NULL) {
643 printf("out of memory\n");
644 exit(1);
645 }
646 free(cur_machine_x11_disp[i]);
647 cur_machine_x11_disp[i] = NULL;
648 }
649
650 emul_machine_setup(m,
651 cur_machine_n_load, cur_machine_load,
652 cur_machine_n_device, cur_machine_device);
653
654 for (i=0; i<cur_machine_n_device; i++) {
655 free(cur_machine_device[i]);
656 cur_machine_device[i] = NULL;
657 }
658
659 for (i=0; i<cur_machine_n_load; i++) {
660 free(cur_machine_load[i]);
661 cur_machine_load[i] = NULL;
662 }
663
664 *parsestate = PARSESTATE_EMUL;
665 return;
666 }
667
668 WORD("name", cur_machine_name);
669 WORD("cpu", cur_machine_cpu);
670 WORD("type", cur_machine_type);
671 WORD("subtype", cur_machine_subtype);
672 WORD("bootname", cur_machine_bootname);
673 WORD("bootarg", cur_machine_bootarg);
674 WORD("slow_serial_interrupts_hack_for_linux", cur_machine_slowsi);
675 WORD("debugger_on_badaddr", cur_machine_debugger_on_badaddr);
676 WORD("prom_emulation", cur_machine_prom_emulation);
677 WORD("use_x11", cur_machine_use_x11);
678 WORD("x11_scaledown", cur_machine_x11_scaledown);
679 WORD("bintrans", cur_machine_bintrans);
680 WORD("old_bintrans", cur_machine_old_bintrans);
681 WORD("bintrans_size", cur_machine_bintrans_size);
682 WORD("byte_order", cur_machine_byte_order);
683 WORD("random_mem_contents", cur_machine_random_mem);
684 WORD("use_random_bootstrap_cpu", cur_machine_random_cpu);
685 WORD("force_netboot", cur_machine_force_netboot);
686 WORD("ncpus", cur_machine_ncpus);
687 WORD("serial_nr", cur_machine_serial_nr);
688 WORD("n_gfx_cards", cur_machine_n_gfx_cards);
689 WORD("emulated_hz", cur_machine_emulated_hz);
690 WORD("memory", cur_machine_memory);
691 WORD("start_paused", cur_machine_start_paused);
692
693 if (strcmp(word, "load") == 0) {
694 read_one_word(f, word, maxbuflen,
695 line, EXPECT_LEFT_PARENTHESIS);
696 if (cur_machine_n_load >= MAX_N_LOAD) {
697 fprintf(stderr, "too many loads\n");
698 exit(1);
699 }
700 cur_machine_load[cur_machine_n_load] = malloc(MAX_LOAD_LEN);
701 if (cur_machine_load[cur_machine_n_load] == NULL) {
702 fprintf(stderr, "out of memory\n");
703 exit(1);
704 }
705 read_one_word(f, cur_machine_load[cur_machine_n_load],
706 MAX_LOAD_LEN, line, EXPECT_WORD);
707 cur_machine_n_load ++;
708 read_one_word(f, word, maxbuflen,
709 line, EXPECT_RIGHT_PARENTHESIS);
710 return;
711 }
712
713 if (strcmp(word, "disk") == 0) {
714 read_one_word(f, word, maxbuflen,
715 line, EXPECT_LEFT_PARENTHESIS);
716 if (cur_machine_n_disk >= MAX_N_DISK) {
717 fprintf(stderr, "too many disks\n");
718 exit(1);
719 }
720 cur_machine_disk[cur_machine_n_disk] = malloc(MAX_DISK_LEN);
721 if (cur_machine_disk[cur_machine_n_disk] == NULL) {
722 fprintf(stderr, "out of memory\n");
723 exit(1);
724 }
725 read_one_word(f, cur_machine_disk[cur_machine_n_disk],
726 MAX_DISK_LEN, line, EXPECT_WORD);
727 cur_machine_n_disk ++;
728 read_one_word(f, word, maxbuflen,
729 line, EXPECT_RIGHT_PARENTHESIS);
730 return;
731 }
732
733 if (strcmp(word, "device") == 0) {
734 read_one_word(f, word, maxbuflen,
735 line, EXPECT_LEFT_PARENTHESIS);
736 if (cur_machine_n_device >= MAX_N_DEVICE) {
737 fprintf(stderr, "too many devices\n");
738 exit(1);
739 }
740 cur_machine_device[cur_machine_n_device] =
741 malloc(MAX_DEVICE_LEN);
742 if (cur_machine_device[cur_machine_n_device] == NULL) {
743 fprintf(stderr, "out of memory\n");
744 exit(1);
745 }
746 read_one_word(f, cur_machine_device[cur_machine_n_device],
747 MAX_DEVICE_LEN, line, EXPECT_WORD);
748 cur_machine_n_device ++;
749 read_one_word(f, word, maxbuflen,
750 line, EXPECT_RIGHT_PARENTHESIS);
751 return;
752 }
753
754 if (strcmp(word, "add_x11_display") == 0) {
755 read_one_word(f, word, maxbuflen,
756 line, EXPECT_LEFT_PARENTHESIS);
757 if (cur_machine_n_x11_disp >= MAX_N_X11_DISP) {
758 fprintf(stderr, "too many x11 displays\n");
759 exit(1);
760 }
761 cur_machine_x11_disp[cur_machine_n_x11_disp] =
762 malloc(MAX_X11_DISP_LEN);
763 if (cur_machine_x11_disp[cur_machine_n_x11_disp] == NULL) {
764 fprintf(stderr, "out of memory\n");
765 exit(1);
766 }
767 read_one_word(f, cur_machine_x11_disp[cur_machine_n_x11_disp],
768 MAX_X11_DISP_LEN, line, EXPECT_WORD);
769 cur_machine_n_x11_disp ++;
770 read_one_word(f, word, maxbuflen,
771 line, EXPECT_RIGHT_PARENTHESIS);
772 return;
773 }
774
775 fatal("line %i: not expecting '%s' in a 'machine' section\n",
776 *line, word);
777 exit(1);
778 }
779
780
781 /*
782 * emul_parse_config():
783 *
784 * Set up an emulation by parsing a config file.
785 */
786 void emul_parse_config(struct emul *e, FILE *f)
787 {
788 char word[500];
789 int in_emul = 0;
790 int line = 1;
791 int parsestate = PARSESTATE_NONE;
792
793 /* debug("emul_parse_config()\n"); */
794
795 while (!feof(f)) {
796 read_one_word(f, word, sizeof(word), &line,
797 EXPECT_WORD | EXPECT_RIGHT_PARENTHESIS);
798 if (!word[0])
799 break;
800
801 /* debug("word = '%s'\n", word); */
802
803 switch (parsestate) {
804 case PARSESTATE_NONE:
805 parse__none(e, f, &in_emul, &line, &parsestate,
806 word, sizeof(word));
807 break;
808 case PARSESTATE_EMUL:
809 parse__emul(e, f, &in_emul, &line, &parsestate,
810 word, sizeof(word));
811 break;
812 case PARSESTATE_NET:
813 parse__net(e, f, &in_emul, &line, &parsestate,
814 word, sizeof(word));
815 break;
816 case PARSESTATE_MACHINE:
817 parse__machine(e, f, &in_emul, &line, &parsestate,
818 word, sizeof(word));
819 break;
820 default:
821 fatal("INTERNAL ERROR in emul_parse.c ("
822 "parsestate %i is not imlemented yet?)\n",
823 parsestate);
824 exit(1);
825 }
826 }
827
828 if (parsestate != PARSESTATE_NONE) {
829 fatal("EOF but not enough right parentheses?\n");
830 exit(1);
831 }
832 }
833

  ViewVC Help
Powered by ViewVC 1.1.26