/[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 42 - (show 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 /*
2 * Copyright (C) 2005-2007 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.46 2007/06/15 17:02:38 debug Exp $
29 *
30 * Set up an emulation by parsing a config file.
31 *
32 * TODO: REWRITE THIS FROM SCRATCH! :-)
33 */
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 #define MAX_WORD_LEN 200
51
52 #define EXPECT_WORD 1
53 #define EXPECT_LEFT_PARENTHESIS 2
54 #define EXPECT_RIGHT_PARENTHESIS 4
55
56 static int parenthesis_level = 0;
57
58
59 /*
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 parenthesis_level ++;
178 buf[curlen++] = ch;
179 break;
180 }
181 if ((expect & EXPECT_RIGHT_PARENTHESIS) && ch == ')') {
182 parenthesis_level --;
183 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 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
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 static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line,
260 int *parsestate, char *word, size_t maxbuflen);
261
262
263 /*
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 fprintf(stderr, "parse_on_off(): WARNING: unknown value '%s'\n", s);
280
281 return 0;
282 }
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 CHECK_ALLOCATION(e->name = strdup(tmp));
310 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 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 strlcpy(cur_net_local_port, "", sizeof(cur_net_local_port));
325 cur_net_n_remote = 0;
326 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 * Simple words: ipv4net, ipv4len, local_port
372 *
373 * Complex: add_remote
374 *
375 * 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 int i;
382
383 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 if (!cur_net_local_port[0])
392 strlcpy(cur_net_local_port, "0",
393 sizeof(cur_net_local_port));
394
395 e->net = net_init(e, NET_INIT_FLAG_GATEWAY,
396 cur_net_ipv4net, atoi(cur_net_ipv4len),
397 cur_net_remote, cur_net_n_remote,
398 atoi(cur_net_local_port), NULL);
399
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 for (i=0; i<cur_net_n_remote; i++) {
407 free(cur_net_remote[i]);
408 cur_net_remote[i] = NULL;
409 }
410
411 *parsestate = PARSESTATE_EMUL;
412 return;
413 }
414
415 WORD("ipv4net", cur_net_ipv4net);
416 WORD("ipv4len", cur_net_ipv4len);
417 WORD("local_port", cur_net_local_port);
418
419 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
427 CHECK_ALLOCATION(cur_net_remote[cur_net_n_remote] =
428 malloc(MAX_REMOTE_LEN));
429 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 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 strlcpy(cur_machine_name, "no_name",
456 sizeof(cur_machine_name));
457
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 CHECK_ALLOCATION(m->cpu_name = strdup(cur_machine_cpu));
467
468 if (!cur_machine_use_x11[0])
469 strlcpy(cur_machine_use_x11, "no",
470 sizeof(cur_machine_use_x11));
471 m->x11_md.in_use = parse_on_off(cur_machine_use_x11);
472
473 if (!cur_machine_slowsi[0])
474 strlcpy(cur_machine_slowsi, "no",
475 sizeof(cur_machine_slowsi));
476 m->slow_serial_interrupts_hack_for_linux =
477 parse_on_off(cur_machine_slowsi);
478
479 if (!cur_machine_prom_emulation[0])
480 strlcpy(cur_machine_prom_emulation, "yes",
481 sizeof(cur_machine_prom_emulation));
482 m->prom_emulation = parse_on_off(cur_machine_prom_emulation);
483
484 if (!cur_machine_random_mem[0])
485 strlcpy(cur_machine_random_mem, "no",
486 sizeof(cur_machine_random_mem));
487 m->random_mem_contents =
488 parse_on_off(cur_machine_random_mem);
489
490 if (!cur_machine_random_cpu[0])
491 strlcpy(cur_machine_random_cpu, "no",
492 sizeof(cur_machine_random_cpu));
493 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 strlcpy(cur_machine_force_netboot, "no",
512 sizeof(cur_machine_force_netboot));
513 m->force_netboot = parse_on_off(cur_machine_force_netboot);
514
515 if (!cur_machine_start_paused[0])
516 strlcpy(cur_machine_start_paused, "no",
517 sizeof(cur_machine_start_paused));
518 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 strlcpy(cur_machine_ncpus, "0",
523 sizeof(cur_machine_ncpus));
524 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 strlcpy(cur_machine_memory, "0",
542 sizeof(cur_machine_memory));
543 m->physical_ram_in_mb = atoi(cur_machine_memory);
544
545 if (!cur_machine_x11_scaledown[0])
546 m->x11_md.scaledown = 1;
547 else {
548 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 }
553 if (m->x11_md.scaledown < 1) {
554 fprintf(stderr, "Invalid scaledown value"
555 " (%i)\n", m->x11_md.scaledown);
556 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 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 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 CHECK_ALLOCATION(cur_machine_load[cur_machine_n_load] =
630 malloc(MAX_LOAD_LEN));
631 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 CHECK_ALLOCATION(cur_machine_disk[cur_machine_n_disk] =
647 malloc(MAX_DISK_LEN));
648 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 CHECK_ALLOCATION(cur_machine_device[cur_machine_n_device] =
664 malloc(MAX_DEVICE_LEN));
665 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 CHECK_ALLOCATION(cur_machine_x11_disp[cur_machine_n_x11_disp] =
681 malloc(MAX_X11_DISP_LEN));
682 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 void emul_parse_config(struct emul *e, char *fname)
702 {
703 FILE *f = fopen(fname, "r");
704 char word[MAX_WORD_LEN];
705 int in_emul = 0;
706 int line = 1;
707 int parsestate = PARSESTATE_EMUL;
708
709 /* debug("emul_parse_config()\n"); */
710 if (f == NULL) {
711 perror(fname);
712 exit(1);
713 }
714
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 case PARSESTATE_NONE:
737 break;
738 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 if (parenthesis_level != 0) {
747 fatal("EOF but not enough right parentheses?\n");
748 exit(1);
749 }
750
751 fclose(f);
752 }
753

  ViewVC Help
Powered by ViewVC 1.1.26