/[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

Annotation of /trunk/src/emul_parse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide 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 dpavlin 2 /*
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 dpavlin 10 * $Id: emul_parse.c,v 1.32 2005/06/24 09:33:34 debug Exp $
29 dpavlin 2 *
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 dpavlin 10 * XML is ugly. It is ugly right now as well. The question is: which
34     * solution is the least ugly?
35 dpavlin 2 */
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 dpavlin 10 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 dpavlin 2
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 dpavlin 10 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 dpavlin 2 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 dpavlin 10 * Simple words: ipv4net, ipv4len, local_port
401 dpavlin 2 *
402 dpavlin 10 * Complex: add_remote
403     *
404 dpavlin 2 * 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 dpavlin 10 int i;
411    
412 dpavlin 2 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 dpavlin 10 if (!cur_net_local_port[0])
421     strlcpy(cur_net_local_port, "0",
422     sizeof(cur_net_local_port));
423    
424 dpavlin 2 e->net = net_init(e, NET_INIT_FLAG_GATEWAY,
425 dpavlin 10 cur_net_ipv4net, atoi(cur_net_ipv4len),
426     cur_net_remote, cur_net_n_remote,
427     atoi(cur_net_local_port));
428 dpavlin 2
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 dpavlin 10 for (i=0; i<cur_net_n_remote; i++) {
436     free(cur_net_remote[i]);
437     cur_net_remote[i] = NULL;
438     }
439    
440 dpavlin 2 *parsestate = PARSESTATE_EMUL;
441     return;
442     }
443    
444     WORD("ipv4net", cur_net_ipv4net);
445     WORD("ipv4len", cur_net_ipv4len);
446 dpavlin 10 WORD("local_port", cur_net_local_port);
447 dpavlin 2
448 dpavlin 10 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 dpavlin 2 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 dpavlin 10 strlcpy(cur_machine_name, "no_name",
487     sizeof(cur_machine_name));
488 dpavlin 2
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 dpavlin 10 strlcpy(cur_machine_use_x11, "no",
501     sizeof(cur_machine_use_x11));
502 dpavlin 2 m->use_x11 = parse_on_off(cur_machine_use_x11);
503    
504     if (!cur_machine_slowsi[0])
505 dpavlin 10 strlcpy(cur_machine_slowsi, "no",
506     sizeof(cur_machine_slowsi));
507 dpavlin 2 m->slow_serial_interrupts_hack_for_linux =
508     parse_on_off(cur_machine_slowsi);
509    
510     if (!cur_machine_debugger_on_badaddr[0])
511 dpavlin 10 strlcpy(cur_machine_debugger_on_badaddr, "no",
512     sizeof(cur_machine_debugger_on_badaddr));
513 dpavlin 2 m->single_step_on_bad_addr =
514     parse_on_off(cur_machine_debugger_on_badaddr);
515    
516     if (!cur_machine_prom_emulation[0])
517 dpavlin 10 strlcpy(cur_machine_prom_emulation, "yes",
518     sizeof(cur_machine_prom_emulation));
519 dpavlin 2 m->prom_emulation = parse_on_off(cur_machine_prom_emulation);
520    
521     if (!cur_machine_random_mem[0])
522 dpavlin 10 strlcpy(cur_machine_random_mem, "no",
523     sizeof(cur_machine_random_mem));
524 dpavlin 2 m->random_mem_contents =
525     parse_on_off(cur_machine_random_mem);
526    
527     if (!cur_machine_random_cpu[0])
528 dpavlin 10 strlcpy(cur_machine_random_cpu, "no",
529     sizeof(cur_machine_random_cpu));
530 dpavlin 2 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 dpavlin 10 strlcpy(cur_machine_bintrans, "yes",
549     sizeof(cur_machine_bintrans));
550 dpavlin 2 m->bintrans_enable = m->bintrans_enabled_from_start =
551     parse_on_off(cur_machine_bintrans);
552    
553     if (!cur_machine_old_bintrans[0])
554 dpavlin 10 strlcpy(cur_machine_old_bintrans, "yes",
555     sizeof(cur_machine_old_bintrans));
556 dpavlin 2 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 dpavlin 10 strlcpy(cur_machine_force_netboot, "no",
574     sizeof(cur_machine_force_netboot));
575 dpavlin 2 m->force_netboot = parse_on_off(cur_machine_force_netboot);
576    
577     if (!cur_machine_start_paused[0])
578 dpavlin 10 strlcpy(cur_machine_start_paused, "no",
579     sizeof(cur_machine_start_paused));
580 dpavlin 2 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 dpavlin 10 strlcpy(cur_machine_ncpus, "0",
585     sizeof(cur_machine_ncpus));
586 dpavlin 2 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 dpavlin 10 strlcpy(cur_machine_memory, "0",
605     sizeof(cur_machine_memory));
606 dpavlin 2 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