/[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 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 20166 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


1 dpavlin 2 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 2 *
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 42 * $Id: emul_parse.c,v 1.46 2007/06/15 17:02:38 debug Exp $
29 dpavlin 2 *
30     * Set up an emulation by parsing a config file.
31     *
32 dpavlin 24 * TODO: REWRITE THIS FROM SCRATCH! :-)
33 dpavlin 2 */
34    
35     #include <stdio.h>
36     #include <stdlib.h>
37     #include <string.h>
38    
39     #include "diskimage.h"
40     #include "emul.h"
41     #include "machine.h"
42     #include "misc.h"
43     #include "net.h"
44    
45    
46     #define is_word_char(ch) ( \
47     (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || \
48     ch == '_' || ch == '$' || (ch >= '0' && ch <= '9') )
49    
50 dpavlin 24 #define MAX_WORD_LEN 200
51 dpavlin 2
52     #define EXPECT_WORD 1
53     #define EXPECT_LEFT_PARENTHESIS 2
54     #define EXPECT_RIGHT_PARENTHESIS 4
55    
56 dpavlin 24 static int parenthesis_level = 0;
57 dpavlin 2
58 dpavlin 24
59 dpavlin 2 /*
60     * read_one_word():
61     *
62     * Reads the file f until it has read a complete word. Whitespace is ignored,
63     * and also any exclamation mark ('!') and anything following an exclamation
64     * mark on a line.
65     *
66     * Used internally by emul_parse_config().
67     */
68     static void read_one_word(FILE *f, char *buf, int buflen, int *line,
69     int expect)
70     {
71     int ch;
72     int done = 0;
73     int curlen = 0;
74     int in_word = 0;
75    
76     while (!done) {
77     if (curlen >= buflen - 1)
78     break;
79    
80     ch = fgetc(f);
81     if (ch == EOF)
82     break;
83    
84     if (in_word) {
85     if (is_word_char(ch)) {
86     buf[curlen++] = ch;
87     if (curlen == buflen - 1)
88     done = 1;
89     continue;
90     } else {
91     if (ungetc(ch, f) == EOF) {
92     fatal("ungetc() failed?\n");
93     exit(1);
94     }
95     break;
96     }
97     }
98    
99     if (ch == '\n') {
100     (*line) ++;
101     continue;
102     }
103    
104     if (ch == '\r')
105     continue;
106    
107     if (ch == '!') {
108     /* Skip until newline: */
109     while (ch != '\n' && ch != EOF)
110     ch = fgetc(f);
111     if (ch == '\n')
112     (*line) ++;
113     continue;
114     }
115    
116     if (ch == '{') {
117     int depth = 1;
118    
119     /* Skip until '}': */
120     while (depth > 0) {
121     ch = fgetc(f);
122     if (ch == '\n')
123     (*line) ++;
124     if (ch == '{')
125     depth ++;
126     if (ch == '}')
127     depth --;
128     if (ch == EOF) {
129     fatal("line %i: unexpected EOF inside"
130     " a nested comment\n", *line);
131     exit(1);
132     }
133     }
134     continue;
135     }
136    
137     /* Whitespace? */
138     if (ch <= ' ')
139     continue;
140    
141     if (ch == '"' || ch == '\'') {
142     /* This is a quoted word. */
143     int start_ch = ch;
144    
145     if (expect & EXPECT_LEFT_PARENTHESIS) {
146     fatal("unexpected character '%c', line %i\n",
147     ch, *line);
148     exit(1);
149     }
150    
151     while (curlen < buflen - 1) {
152     ch = fgetc(f);
153     if (ch == '\n') {
154     fatal("line %i: newline inside"
155     " quotes?\n", *line);
156     exit(1);
157     }
158     if (ch == EOF) {
159     fatal("line %i: EOF inside a quoted"
160     " string?\n", *line);
161     exit(1);
162     }
163     if (ch == start_ch)
164     break;
165     buf[curlen++] = ch;
166     }
167     break;
168     }
169    
170     if ((expect & EXPECT_WORD) && is_word_char(ch)) {
171     buf[curlen++] = ch;
172     in_word = 1;
173     if (curlen == buflen - 1)
174     done = 1;
175     } else {
176     if ((expect & EXPECT_LEFT_PARENTHESIS) && ch == '(') {
177 dpavlin 24 parenthesis_level ++;
178 dpavlin 2 buf[curlen++] = ch;
179     break;
180     }
181     if ((expect & EXPECT_RIGHT_PARENTHESIS) && ch == ')') {
182 dpavlin 24 parenthesis_level --;
183 dpavlin 2 buf[curlen++] = ch;
184     break;
185     }
186    
187     fatal("unexpected character '%c', line %i\n",
188     ch, *line);
189     exit(1);
190     }
191     }
192    
193     buf[curlen] = '\0';
194     }
195    
196    
197     #define PARSESTATE_NONE 0
198     #define PARSESTATE_EMUL 1
199     #define PARSESTATE_NET 2
200     #define PARSESTATE_MACHINE 3
201    
202     static char cur_net_ipv4net[50];
203     static char cur_net_ipv4len[50];
204 dpavlin 10 static char cur_net_local_port[10];
205     #define MAX_N_REMOTE 20
206     #define MAX_REMOTE_LEN 100
207     static char *cur_net_remote[MAX_N_REMOTE];
208     static int cur_net_n_remote;
209 dpavlin 2
210     static char cur_machine_name[50];
211     static char cur_machine_cpu[50];
212     static char cur_machine_type[50];
213     static char cur_machine_subtype[50];
214     static char cur_machine_bootname[150];
215     static char cur_machine_bootarg[250];
216     static char cur_machine_slowsi[10];
217     static char cur_machine_prom_emulation[10];
218     static char cur_machine_use_x11[10];
219     static char cur_machine_x11_scaledown[10];
220     static char cur_machine_byte_order[20];
221     static char cur_machine_random_mem[10];
222     static char cur_machine_random_cpu[10];
223     static char cur_machine_force_netboot[10];
224     static char cur_machine_start_paused[10];
225     static char cur_machine_ncpus[10];
226     static char cur_machine_n_gfx_cards[10];
227     static char cur_machine_serial_nr[10];
228     static char cur_machine_emulated_hz[10];
229     static char cur_machine_memory[10];
230     #define MAX_N_LOAD 15
231     #define MAX_LOAD_LEN 2000
232     static char *cur_machine_load[MAX_N_LOAD];
233     static int cur_machine_n_load;
234     #define MAX_N_DISK 10
235     #define MAX_DISK_LEN 2000
236     static char *cur_machine_disk[MAX_N_DISK];
237     static int cur_machine_n_disk;
238     #define MAX_N_DEVICE 20
239     #define MAX_DEVICE_LEN 400
240     static char *cur_machine_device[MAX_N_DISK];
241     static int cur_machine_n_device;
242     #define MAX_N_X11_DISP 5
243     #define MAX_X11_DISP_LEN 1000
244     static char *cur_machine_x11_disp[MAX_N_X11_DISP];
245     static int cur_machine_n_x11_disp;
246    
247     #define WORD(w,var) { \
248     if (strcmp(word, w) == 0) { \
249     read_one_word(f, word, maxbuflen, \
250     line, EXPECT_LEFT_PARENTHESIS); \
251     read_one_word(f, var, sizeof(var), \
252     line, EXPECT_WORD); \
253     read_one_word(f, word, maxbuflen, \
254     line, EXPECT_RIGHT_PARENTHESIS); \
255     return; \
256     } \
257     }
258    
259 dpavlin 24 static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line,
260     int *parsestate, char *word, size_t maxbuflen);
261 dpavlin 2
262 dpavlin 24
263 dpavlin 2 /*
264     * parse_on_off():
265     *
266     * Returns 1 for "on", "yes", "enable", or "1".
267     * Returns 0 for "off", "no", "disable", or "0".
268     * Prints a fatal warning and exit()s for other values.
269     */
270     int parse_on_off(char *s)
271     {
272     if (strcasecmp(s, "on") == 0 || strcasecmp(s, "yes") == 0 ||
273     strcasecmp(s, "enable") == 0 || strcasecmp(s, "1") == 0)
274     return 1;
275     if (strcasecmp(s, "off") == 0 || strcasecmp(s, "no") == 0 ||
276     strcasecmp(s, "disable") == 0 || strcasecmp(s, "0") == 0)
277     return 0;
278    
279 dpavlin 24 fprintf(stderr, "parse_on_off(): WARNING: unknown value '%s'\n", s);
280 dpavlin 2
281 dpavlin 24 return 0;
282 dpavlin 2 }
283    
284    
285     /*
286     * parse__emul():
287     *
288     * name, net, machine
289     */
290     static void parse__emul(struct emul *e, FILE *f, int *in_emul, int *line,
291     int *parsestate, char *word, size_t maxbuflen)
292     {
293     if (word[0] == ')') {
294     *parsestate = PARSESTATE_NONE;
295     return;
296     }
297    
298     if (strcmp(word, "name") == 0) {
299     char tmp[200];
300     read_one_word(f, word, maxbuflen,
301     line, EXPECT_LEFT_PARENTHESIS);
302     read_one_word(f, tmp, sizeof(tmp), line, EXPECT_WORD);
303     read_one_word(f, word, maxbuflen,
304     line, EXPECT_RIGHT_PARENTHESIS);
305     if (e->name != NULL) {
306     free(e->name);
307     e->name = NULL;
308     }
309 dpavlin 42 CHECK_ALLOCATION(e->name = strdup(tmp));
310 dpavlin 2 debug("name: \"%s\"\n", e->name);
311     return;
312     }
313    
314     if (strcmp(word, "net") == 0) {
315     *parsestate = PARSESTATE_NET;
316     read_one_word(f, word, maxbuflen,
317     line, EXPECT_LEFT_PARENTHESIS);
318    
319     /* Default net: */
320 dpavlin 32 strlcpy(cur_net_ipv4net, NET_DEFAULT_IPV4_MASK,
321     sizeof(cur_net_ipv4net));
322     snprintf(cur_net_ipv4len, sizeof(cur_net_ipv4len), "%i",
323     NET_DEFAULT_IPV4_LEN);
324 dpavlin 10 strlcpy(cur_net_local_port, "", sizeof(cur_net_local_port));
325     cur_net_n_remote = 0;
326 dpavlin 2 return;
327     }
328    
329     if (strcmp(word, "machine") == 0) {
330     *parsestate = PARSESTATE_MACHINE;
331     read_one_word(f, word, maxbuflen,
332     line, EXPECT_LEFT_PARENTHESIS);
333    
334     /* A "zero state": */
335     cur_machine_name[0] = '\0';
336     cur_machine_cpu[0] = '\0';
337     cur_machine_type[0] = '\0';
338     cur_machine_subtype[0] = '\0';
339     cur_machine_bootname[0] = '\0';
340     cur_machine_bootarg[0] = '\0';
341     cur_machine_n_load = 0;
342     cur_machine_n_disk = 0;
343     cur_machine_n_device = 0;
344     cur_machine_n_x11_disp = 0;
345     cur_machine_slowsi[0] = '\0';
346     cur_machine_prom_emulation[0] = '\0';
347     cur_machine_use_x11[0] = '\0';
348     cur_machine_x11_scaledown[0] = '\0';
349     cur_machine_byte_order[0] = '\0';
350     cur_machine_random_mem[0] = '\0';
351     cur_machine_random_cpu[0] = '\0';
352     cur_machine_force_netboot[0] = '\0';
353     cur_machine_start_paused[0] = '\0';
354     cur_machine_ncpus[0] = '\0';
355     cur_machine_n_gfx_cards[0] = '\0';
356     cur_machine_serial_nr[0] = '\0';
357     cur_machine_emulated_hz[0] = '\0';
358     cur_machine_memory[0] = '\0';
359     return;
360     }
361    
362     fatal("line %i: not expecting '%s' in an 'emul' section\n",
363     *line, word);
364     exit(1);
365     }
366    
367    
368     /*
369     * parse__net():
370     *
371 dpavlin 10 * Simple words: ipv4net, ipv4len, local_port
372 dpavlin 2 *
373 dpavlin 10 * Complex: add_remote
374     *
375 dpavlin 2 * TODO: more words? for example an option to disable the gateway? that would
376     * have to be implemented correctly in src/net.c first.
377     */
378     static void parse__net(struct emul *e, FILE *f, int *in_emul, int *line,
379     int *parsestate, char *word, size_t maxbuflen)
380     {
381 dpavlin 10 int i;
382    
383 dpavlin 2 if (word[0] == ')') {
384     /* Finished with the 'net' section. Let's create the net: */
385     if (e->net != NULL) {
386     fatal("line %i: more than one net isn't really "
387     "supported yet\n", *line);
388     exit(1);
389     }
390    
391 dpavlin 10 if (!cur_net_local_port[0])
392     strlcpy(cur_net_local_port, "0",
393     sizeof(cur_net_local_port));
394    
395 dpavlin 2 e->net = net_init(e, NET_INIT_FLAG_GATEWAY,
396 dpavlin 10 cur_net_ipv4net, atoi(cur_net_ipv4len),
397     cur_net_remote, cur_net_n_remote,
398 dpavlin 32 atoi(cur_net_local_port), NULL);
399 dpavlin 2
400     if (e->net == NULL) {
401     fatal("line %i: fatal error: could not create"
402     " the net (?)\n", *line);
403     exit(1);
404     }
405    
406 dpavlin 10 for (i=0; i<cur_net_n_remote; i++) {
407     free(cur_net_remote[i]);
408     cur_net_remote[i] = NULL;
409     }
410    
411 dpavlin 2 *parsestate = PARSESTATE_EMUL;
412     return;
413     }
414    
415     WORD("ipv4net", cur_net_ipv4net);
416     WORD("ipv4len", cur_net_ipv4len);
417 dpavlin 10 WORD("local_port", cur_net_local_port);
418 dpavlin 2
419 dpavlin 10 if (strcmp(word, "add_remote") == 0) {
420     read_one_word(f, word, maxbuflen,
421     line, EXPECT_LEFT_PARENTHESIS);
422     if (cur_net_n_remote >= MAX_N_REMOTE) {
423     fprintf(stderr, "too many remote networks\n");
424     exit(1);
425     }
426 dpavlin 42
427     CHECK_ALLOCATION(cur_net_remote[cur_net_n_remote] =
428     malloc(MAX_REMOTE_LEN));
429 dpavlin 10 read_one_word(f, cur_net_remote[cur_net_n_remote],
430     MAX_REMOTE_LEN, line, EXPECT_WORD);
431     cur_net_n_remote ++;
432     read_one_word(f, word, maxbuflen, line,
433     EXPECT_RIGHT_PARENTHESIS);
434     return;
435     }
436    
437 dpavlin 2 fatal("line %i: not expecting '%s' in a 'net' section\n", *line, word);
438     exit(1);
439     }
440    
441    
442     /*
443     * parse__machine():
444     */
445     static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line,
446     int *parsestate, char *word, size_t maxbuflen)
447     {
448     int r, i;
449    
450     if (word[0] == ')') {
451     /* Finished with the 'machine' section. */
452     struct machine *m;
453    
454     if (!cur_machine_name[0])
455 dpavlin 10 strlcpy(cur_machine_name, "no_name",
456     sizeof(cur_machine_name));
457 dpavlin 2
458     m = emul_add_machine(e, cur_machine_name);
459    
460     r = machine_name_to_type(cur_machine_type, cur_machine_subtype,
461     &m->machine_type, &m->machine_subtype, &m->arch);
462     if (!r)
463     exit(1);
464    
465     if (cur_machine_cpu[0])
466 dpavlin 42 CHECK_ALLOCATION(m->cpu_name = strdup(cur_machine_cpu));
467 dpavlin 2
468     if (!cur_machine_use_x11[0])
469 dpavlin 10 strlcpy(cur_machine_use_x11, "no",
470     sizeof(cur_machine_use_x11));
471 dpavlin 42 m->x11_md.in_use = parse_on_off(cur_machine_use_x11);
472 dpavlin 2
473     if (!cur_machine_slowsi[0])
474 dpavlin 10 strlcpy(cur_machine_slowsi, "no",
475     sizeof(cur_machine_slowsi));
476 dpavlin 2 m->slow_serial_interrupts_hack_for_linux =
477     parse_on_off(cur_machine_slowsi);
478    
479     if (!cur_machine_prom_emulation[0])
480 dpavlin 10 strlcpy(cur_machine_prom_emulation, "yes",
481     sizeof(cur_machine_prom_emulation));
482 dpavlin 2 m->prom_emulation = parse_on_off(cur_machine_prom_emulation);
483    
484     if (!cur_machine_random_mem[0])
485 dpavlin 10 strlcpy(cur_machine_random_mem, "no",
486     sizeof(cur_machine_random_mem));
487 dpavlin 2 m->random_mem_contents =
488     parse_on_off(cur_machine_random_mem);
489    
490     if (!cur_machine_random_cpu[0])
491 dpavlin 10 strlcpy(cur_machine_random_cpu, "no",
492     sizeof(cur_machine_random_cpu));
493 dpavlin 2 m->use_random_bootstrap_cpu =
494     parse_on_off(cur_machine_random_cpu);
495    
496     m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;
497     if (cur_machine_byte_order[0]) {
498     if (strncasecmp(cur_machine_byte_order, "big", 3) == 0)
499     m->byte_order_override = EMUL_BIG_ENDIAN;
500     else if (strncasecmp(cur_machine_byte_order, "little",
501     6) == 0)
502     m->byte_order_override = EMUL_LITTLE_ENDIAN;
503     else {
504     fatal("Byte order must be big-endian or"
505     " little-endian\n");
506     exit(1);
507     }
508     }
509    
510     if (!cur_machine_force_netboot[0])
511 dpavlin 10 strlcpy(cur_machine_force_netboot, "no",
512     sizeof(cur_machine_force_netboot));
513 dpavlin 2 m->force_netboot = parse_on_off(cur_machine_force_netboot);
514    
515     if (!cur_machine_start_paused[0])
516 dpavlin 10 strlcpy(cur_machine_start_paused, "no",
517     sizeof(cur_machine_start_paused));
518 dpavlin 2 m->start_paused = parse_on_off(cur_machine_start_paused);
519    
520     /* NOTE: Default nr of CPUs is 0: */
521     if (!cur_machine_ncpus[0])
522 dpavlin 10 strlcpy(cur_machine_ncpus, "0",
523     sizeof(cur_machine_ncpus));
524 dpavlin 2 m->ncpus = atoi(cur_machine_ncpus);
525    
526     if (cur_machine_n_gfx_cards[0])
527     m->n_gfx_cards = atoi(cur_machine_n_gfx_cards);
528    
529     if (cur_machine_serial_nr[0]) {
530     m->serial_nr = atoi(cur_machine_serial_nr);
531     e->next_serial_nr = m->serial_nr+1;
532     }
533    
534     if (cur_machine_emulated_hz[0]) {
535     m->emulated_hz = mystrtoull(cur_machine_emulated_hz,
536     NULL, 0);
537     }
538    
539     /* NOTE: Default nr of CPUs is 0: */
540     if (!cur_machine_memory[0])
541 dpavlin 10 strlcpy(cur_machine_memory, "0",
542     sizeof(cur_machine_memory));
543 dpavlin 2 m->physical_ram_in_mb = atoi(cur_machine_memory);
544    
545     if (!cur_machine_x11_scaledown[0])
546 dpavlin 42 m->x11_md.scaledown = 1;
547 dpavlin 2 else {
548 dpavlin 42 m->x11_md.scaledown = atoi(cur_machine_x11_scaledown);
549     if (m->x11_md.scaledown < 0) {
550     m->x11_md.scaleup = 0 - m->x11_md.scaledown;
551     m->x11_md.scaledown = 1;
552 dpavlin 20 }
553 dpavlin 42 if (m->x11_md.scaledown < 1) {
554 dpavlin 2 fprintf(stderr, "Invalid scaledown value"
555 dpavlin 42 " (%i)\n", m->x11_md.scaledown);
556 dpavlin 2 exit(1);
557     }
558     }
559    
560     for (i=0; i<cur_machine_n_disk; i++) {
561     diskimage_add(m, cur_machine_disk[i]);
562     free(cur_machine_disk[i]);
563     cur_machine_disk[i] = NULL;
564     }
565    
566     m->boot_kernel_filename = strdup(cur_machine_bootname);
567    
568     if (cur_machine_bootarg[0])
569     m->boot_string_argument = strdup(cur_machine_bootarg);
570    
571     for (i=0; i<cur_machine_n_x11_disp; i++) {
572 dpavlin 42 m->x11_md.n_display_names ++;
573     CHECK_ALLOCATION(m->x11_md.display_names = realloc(
574     m->x11_md.display_names, m->x11_md.n_display_names
575     * sizeof(char *)));
576     CHECK_ALLOCATION(m->x11_md.display_names[
577     m->x11_md.n_display_names-1] =
578     strdup(cur_machine_x11_disp[i]));
579 dpavlin 2 free(cur_machine_x11_disp[i]);
580     cur_machine_x11_disp[i] = NULL;
581     }
582    
583     emul_machine_setup(m,
584     cur_machine_n_load, cur_machine_load,
585     cur_machine_n_device, cur_machine_device);
586    
587     for (i=0; i<cur_machine_n_device; i++) {
588     free(cur_machine_device[i]);
589     cur_machine_device[i] = NULL;
590     }
591    
592     for (i=0; i<cur_machine_n_load; i++) {
593     free(cur_machine_load[i]);
594     cur_machine_load[i] = NULL;
595     }
596    
597     *parsestate = PARSESTATE_EMUL;
598     return;
599     }
600    
601     WORD("name", cur_machine_name);
602     WORD("cpu", cur_machine_cpu);
603     WORD("type", cur_machine_type);
604     WORD("subtype", cur_machine_subtype);
605     WORD("bootname", cur_machine_bootname);
606     WORD("bootarg", cur_machine_bootarg);
607     WORD("slow_serial_interrupts_hack_for_linux", cur_machine_slowsi);
608     WORD("prom_emulation", cur_machine_prom_emulation);
609     WORD("use_x11", cur_machine_use_x11);
610     WORD("x11_scaledown", cur_machine_x11_scaledown);
611     WORD("byte_order", cur_machine_byte_order);
612     WORD("random_mem_contents", cur_machine_random_mem);
613     WORD("use_random_bootstrap_cpu", cur_machine_random_cpu);
614     WORD("force_netboot", cur_machine_force_netboot);
615     WORD("ncpus", cur_machine_ncpus);
616     WORD("serial_nr", cur_machine_serial_nr);
617     WORD("n_gfx_cards", cur_machine_n_gfx_cards);
618     WORD("emulated_hz", cur_machine_emulated_hz);
619     WORD("memory", cur_machine_memory);
620     WORD("start_paused", cur_machine_start_paused);
621    
622     if (strcmp(word, "load") == 0) {
623     read_one_word(f, word, maxbuflen,
624     line, EXPECT_LEFT_PARENTHESIS);
625     if (cur_machine_n_load >= MAX_N_LOAD) {
626     fprintf(stderr, "too many loads\n");
627     exit(1);
628     }
629 dpavlin 42 CHECK_ALLOCATION(cur_machine_load[cur_machine_n_load] =
630     malloc(MAX_LOAD_LEN));
631 dpavlin 2 read_one_word(f, cur_machine_load[cur_machine_n_load],
632     MAX_LOAD_LEN, line, EXPECT_WORD);
633     cur_machine_n_load ++;
634     read_one_word(f, word, maxbuflen,
635     line, EXPECT_RIGHT_PARENTHESIS);
636     return;
637     }
638    
639     if (strcmp(word, "disk") == 0) {
640     read_one_word(f, word, maxbuflen,
641     line, EXPECT_LEFT_PARENTHESIS);
642     if (cur_machine_n_disk >= MAX_N_DISK) {
643     fprintf(stderr, "too many disks\n");
644     exit(1);
645     }
646 dpavlin 42 CHECK_ALLOCATION(cur_machine_disk[cur_machine_n_disk] =
647     malloc(MAX_DISK_LEN));
648 dpavlin 2 read_one_word(f, cur_machine_disk[cur_machine_n_disk],
649     MAX_DISK_LEN, line, EXPECT_WORD);
650     cur_machine_n_disk ++;
651     read_one_word(f, word, maxbuflen,
652     line, EXPECT_RIGHT_PARENTHESIS);
653     return;
654     }
655    
656     if (strcmp(word, "device") == 0) {
657     read_one_word(f, word, maxbuflen,
658     line, EXPECT_LEFT_PARENTHESIS);
659     if (cur_machine_n_device >= MAX_N_DEVICE) {
660     fprintf(stderr, "too many devices\n");
661     exit(1);
662     }
663 dpavlin 42 CHECK_ALLOCATION(cur_machine_device[cur_machine_n_device] =
664     malloc(MAX_DEVICE_LEN));
665 dpavlin 2 read_one_word(f, cur_machine_device[cur_machine_n_device],
666     MAX_DEVICE_LEN, line, EXPECT_WORD);
667     cur_machine_n_device ++;
668     read_one_word(f, word, maxbuflen,
669     line, EXPECT_RIGHT_PARENTHESIS);
670     return;
671     }
672    
673     if (strcmp(word, "add_x11_display") == 0) {
674     read_one_word(f, word, maxbuflen,
675     line, EXPECT_LEFT_PARENTHESIS);
676     if (cur_machine_n_x11_disp >= MAX_N_X11_DISP) {
677     fprintf(stderr, "too many x11 displays\n");
678     exit(1);
679     }
680 dpavlin 42 CHECK_ALLOCATION(cur_machine_x11_disp[cur_machine_n_x11_disp] =
681     malloc(MAX_X11_DISP_LEN));
682 dpavlin 2 read_one_word(f, cur_machine_x11_disp[cur_machine_n_x11_disp],
683     MAX_X11_DISP_LEN, line, EXPECT_WORD);
684     cur_machine_n_x11_disp ++;
685     read_one_word(f, word, maxbuflen,
686     line, EXPECT_RIGHT_PARENTHESIS);
687     return;
688     }
689    
690     fatal("line %i: not expecting '%s' in a 'machine' section\n",
691     *line, word);
692     exit(1);
693     }
694    
695    
696     /*
697     * emul_parse_config():
698     *
699     * Set up an emulation by parsing a config file.
700     */
701 dpavlin 24 void emul_parse_config(struct emul *e, char *fname)
702 dpavlin 2 {
703 dpavlin 24 FILE *f = fopen(fname, "r");
704     char word[MAX_WORD_LEN];
705 dpavlin 2 int in_emul = 0;
706     int line = 1;
707 dpavlin 24 int parsestate = PARSESTATE_EMUL;
708 dpavlin 2
709     /* debug("emul_parse_config()\n"); */
710 dpavlin 24 if (f == NULL) {
711     perror(fname);
712     exit(1);
713     }
714 dpavlin 2
715     while (!feof(f)) {
716     read_one_word(f, word, sizeof(word), &line,
717     EXPECT_WORD | EXPECT_RIGHT_PARENTHESIS);
718     if (!word[0])
719     break;
720    
721     /* debug("word = '%s'\n", word); */
722    
723     switch (parsestate) {
724     case PARSESTATE_EMUL:
725     parse__emul(e, f, &in_emul, &line, &parsestate,
726     word, sizeof(word));
727     break;
728     case PARSESTATE_NET:
729     parse__net(e, f, &in_emul, &line, &parsestate,
730     word, sizeof(word));
731     break;
732     case PARSESTATE_MACHINE:
733     parse__machine(e, f, &in_emul, &line, &parsestate,
734     word, sizeof(word));
735     break;
736 dpavlin 24 case PARSESTATE_NONE:
737     break;
738 dpavlin 2 default:
739     fatal("INTERNAL ERROR in emul_parse.c ("
740     "parsestate %i is not imlemented yet?)\n",
741     parsestate);
742     exit(1);
743     }
744     }
745    
746 dpavlin 24 if (parenthesis_level != 0) {
747 dpavlin 2 fatal("EOF but not enough right parentheses?\n");
748     exit(1);
749     }
750 dpavlin 24
751     fclose(f);
752 dpavlin 2 }
753    

  ViewVC Help
Powered by ViewVC 1.1.26