44 |
#include <linux/if.h> |
#include <linux/if.h> |
45 |
#include <linux/if_tun.h> |
#include <linux/if_tun.h> |
46 |
|
|
47 |
#include "cpu-i386.h" |
#include "cpu.h" |
48 |
#include "disas.h" |
#include "disas.h" |
49 |
#include "thunk.h" |
#include "thunk.h" |
50 |
|
|
216 |
BlockDriverState *bs_table[MAX_DISKS]; |
BlockDriverState *bs_table[MAX_DISKS]; |
217 |
int vga_ram_size; |
int vga_ram_size; |
218 |
static DisplayState display_state; |
static DisplayState display_state; |
219 |
int nodisp; |
int nographic; |
220 |
int term_inited; |
int term_inited; |
221 |
int64_t ticks_per_sec; |
int64_t ticks_per_sec; |
222 |
|
|
2434 |
s->select = 0xa0; |
s->select = 0xa0; |
2435 |
} |
} |
2436 |
|
|
2437 |
|
struct partition { |
2438 |
|
uint8_t boot_ind; /* 0x80 - active */ |
2439 |
|
uint8_t head; /* starting head */ |
2440 |
|
uint8_t sector; /* starting sector */ |
2441 |
|
uint8_t cyl; /* starting cylinder */ |
2442 |
|
uint8_t sys_ind; /* What partition type */ |
2443 |
|
uint8_t end_head; /* end head */ |
2444 |
|
uint8_t end_sector; /* end sector */ |
2445 |
|
uint8_t end_cyl; /* end cylinder */ |
2446 |
|
uint32_t start_sect; /* starting sector counting from 0 */ |
2447 |
|
uint32_t nr_sects; /* nr of sectors in partition */ |
2448 |
|
} __attribute__((packed)); |
2449 |
|
|
2450 |
|
/* try to guess the IDE geometry from the MSDOS partition table */ |
2451 |
|
void ide_guess_geometry(IDEState *s) |
2452 |
|
{ |
2453 |
|
uint8_t buf[512]; |
2454 |
|
int ret, i; |
2455 |
|
struct partition *p; |
2456 |
|
uint32_t nr_sects; |
2457 |
|
|
2458 |
|
if (s->cylinders != 0) |
2459 |
|
return; |
2460 |
|
ret = bdrv_read(s->bs, 0, buf, 1); |
2461 |
|
if (ret < 0) |
2462 |
|
return; |
2463 |
|
/* test msdos magic */ |
2464 |
|
if (buf[510] != 0x55 || buf[511] != 0xaa) |
2465 |
|
return; |
2466 |
|
for(i = 0; i < 4; i++) { |
2467 |
|
p = ((struct partition *)(buf + 0x1be)) + i; |
2468 |
|
nr_sects = tswap32(p->nr_sects); |
2469 |
|
if (nr_sects && p->end_head) { |
2470 |
|
/* We make the assumption that the partition terminates on |
2471 |
|
a cylinder boundary */ |
2472 |
|
s->heads = p->end_head + 1; |
2473 |
|
s->sectors = p->end_sector & 63; |
2474 |
|
s->cylinders = s->nb_sectors / (s->heads * s->sectors); |
2475 |
|
#if 0 |
2476 |
|
printf("guessed partition: CHS=%d %d %d\n", |
2477 |
|
s->cylinders, s->heads, s->sectors); |
2478 |
|
#endif |
2479 |
|
} |
2480 |
|
} |
2481 |
|
} |
2482 |
|
|
2483 |
void ide_init(void) |
void ide_init(void) |
2484 |
{ |
{ |
2485 |
IDEState *s; |
IDEState *s; |
2491 |
s->bs = bs_table[i]; |
s->bs = bs_table[i]; |
2492 |
if (s->bs) { |
if (s->bs) { |
2493 |
bdrv_get_geometry(s->bs, &nb_sectors); |
bdrv_get_geometry(s->bs, &nb_sectors); |
2494 |
|
s->nb_sectors = nb_sectors; |
2495 |
|
ide_guess_geometry(s); |
2496 |
if (s->cylinders == 0) { |
if (s->cylinders == 0) { |
2497 |
/* if no geometry, use a LBA compatible one */ |
/* if no geometry, use a LBA compatible one */ |
2498 |
cylinders = nb_sectors / (16 * 63); |
cylinders = nb_sectors / (16 * 63); |
2504 |
s->heads = 16; |
s->heads = 16; |
2505 |
s->sectors = 63; |
s->sectors = 63; |
2506 |
} |
} |
|
s->nb_sectors = nb_sectors; |
|
2507 |
} |
} |
2508 |
s->irq = 14; |
s->irq = 14; |
2509 |
ide_reset(s); |
ide_reset(s); |
3183 |
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |
3184 |
|INLCR|IGNCR|ICRNL|IXON); |
|INLCR|IGNCR|ICRNL|IXON); |
3185 |
tty.c_oflag |= OPOST; |
tty.c_oflag |= OPOST; |
3186 |
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); |
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); |
3187 |
|
/* if graphical mode, we allow Ctrl-C handling */ |
3188 |
|
if (nographic) |
3189 |
|
tty.c_lflag &= ~ISIG; |
3190 |
tty.c_cflag &= ~(CSIZE|PARENB); |
tty.c_cflag &= ~(CSIZE|PARENB); |
3191 |
tty.c_cflag |= CS8; |
tty.c_cflag |= CS8; |
3192 |
tty.c_cc[VMIN] = 1; |
tty.c_cc[VMIN] = 1; |
3288 |
uint8_t ch; |
uint8_t ch; |
3289 |
CPUState *env = global_env; |
CPUState *env = global_env; |
3290 |
|
|
3291 |
if (nodisp && !term_inited) { |
if (!term_inited) { |
3292 |
/* initialize terminal only there so that the user has a |
/* initialize terminal only there so that the user has a |
3293 |
chance to stop QEMU with Ctrl-C before the gdb connection |
chance to stop QEMU with Ctrl-C before the gdb connection |
3294 |
is launched */ |
is launched */ |
3378 |
|
|
3379 |
void help(void) |
void help(void) |
3380 |
{ |
{ |
3381 |
printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
3382 |
"usage: vl [options] [bzImage [kernel parameters...]]\n" |
"usage: qemu [options] [disk_image]\n" |
3383 |
|
"\n" |
3384 |
|
"'disk_image' is a raw hard image image for IDE hard disk 0\n" |
3385 |
"\n" |
"\n" |
3386 |
"'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
"Standard options:\n" |
3387 |
"to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
"-hda file use 'file' as IDE hard disk 0 image\n" |
3388 |
|
"-hdb file use 'file' as IDE hard disk 1 image\n" |
3389 |
|
"-snapshot write to temporary files instead of disk image files\n" |
3390 |
|
"-m megs set virtual RAM size to megs MB\n" |
3391 |
|
"-n script set network init script [default=%s]\n" |
3392 |
|
"-nographic disable graphical output\n" |
3393 |
"\n" |
"\n" |
3394 |
"General options:\n" |
"Linux boot specific (does not require PC BIOS):\n" |
3395 |
"-initrd file use 'file' as initial ram disk\n" |
"-kernel bzImage use 'bzImage' as kernel image\n" |
3396 |
"-hda file use 'file' as hard disk 0 image\n" |
"-append cmdline use 'cmdline' as kernel command line\n" |
3397 |
"-hdb file use 'file' as hard disk 1 image\n" |
"-initrd file use 'file' as initial ram disk\n" |
|
"-snapshot write to temporary files instead of disk image files\n" |
|
|
"-m megs set virtual RAM size to megs MB\n" |
|
|
"-n script set network init script [default=%s]\n" |
|
3398 |
"\n" |
"\n" |
3399 |
"Debug/Expert options:\n" |
"Debug/Expert options:\n" |
3400 |
"-s wait gdb connection to port %d\n" |
"-s wait gdb connection to port %d\n" |
3401 |
"-p port change gdb connection port\n" |
"-p port change gdb connection port\n" |
3402 |
"-d output log in /tmp/vl.log\n" |
"-d output log in /tmp/vl.log\n" |
3403 |
"-hdachs c,h,s force hard disk 0 geometry for non LBA disk images\n" |
"-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" |
3404 |
"-L path set the directory for the BIOS and VGA BIOS\n" |
"-L path set the directory for the BIOS and VGA BIOS\n" |
3405 |
"\n" |
"\n" |
3406 |
"During emulation, use C-a h to get terminal commands:\n", |
"During emulation, use C-a h to get terminal commands:\n", |
3407 |
DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
3415 |
{ "hdb", 1, NULL, 0, }, |
{ "hdb", 1, NULL, 0, }, |
3416 |
{ "snapshot", 0, NULL, 0, }, |
{ "snapshot", 0, NULL, 0, }, |
3417 |
{ "hdachs", 1, NULL, 0, }, |
{ "hdachs", 1, NULL, 0, }, |
3418 |
{ "nodisp", 0, NULL, 0, }, |
{ "nographic", 0, NULL, 0, }, |
3419 |
|
{ "kernel", 1, NULL, 0, }, |
3420 |
|
{ "append", 1, NULL, 0, }, |
3421 |
{ NULL, 0, NULL, 0 }, |
{ NULL, 0, NULL, 0 }, |
3422 |
}; |
}; |
3423 |
|
|
3424 |
|
#ifdef CONFIG_SDL |
3425 |
|
/* SDL use the pthreads and they modify sigaction. We don't |
3426 |
|
want that. */ |
3427 |
|
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) |
3428 |
|
extern void __libc_sigaction(); |
3429 |
|
#define sigaction(sig, act, oact) __libc_sigaction(sig, act, oact) |
3430 |
|
#else |
3431 |
|
extern void __sigaction(); |
3432 |
|
#define sigaction(sig, act, oact) __sigaction(sig, act, oact) |
3433 |
|
#endif |
3434 |
|
#endif /* CONFIG_SDL */ |
3435 |
|
|
3436 |
int main(int argc, char **argv) |
int main(int argc, char **argv) |
3437 |
{ |
{ |
3438 |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
3443 |
CPUX86State *env; |
CPUX86State *env; |
3444 |
const char *tmpdir, *initrd_filename; |
const char *tmpdir, *initrd_filename; |
3445 |
const char *hd_filename[MAX_DISKS]; |
const char *hd_filename[MAX_DISKS]; |
3446 |
|
const char *kernel_filename, *kernel_cmdline; |
3447 |
DisplayState *ds = &display_state; |
DisplayState *ds = &display_state; |
3448 |
|
|
3449 |
/* we never want that malloc() uses mmap() */ |
/* we never want that malloc() uses mmap() */ |
3457 |
use_gdbstub = 0; |
use_gdbstub = 0; |
3458 |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
3459 |
snapshot = 0; |
snapshot = 0; |
3460 |
linux_boot = 0; |
nographic = 0; |
3461 |
nodisp = 0; |
kernel_filename = NULL; |
3462 |
|
kernel_cmdline = ""; |
3463 |
for(;;) { |
for(;;) { |
3464 |
c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
3465 |
if (c == -1) |
if (c == -1) |
3502 |
} |
} |
3503 |
break; |
break; |
3504 |
case 5: |
case 5: |
3505 |
nodisp = 1; |
nographic = 1; |
3506 |
|
break; |
3507 |
|
case 6: |
3508 |
|
kernel_filename = optarg; |
3509 |
|
break; |
3510 |
|
case 7: |
3511 |
|
kernel_cmdline = optarg; |
3512 |
break; |
break; |
3513 |
} |
} |
3514 |
break; |
break; |
3543 |
} |
} |
3544 |
} |
} |
3545 |
|
|
3546 |
linux_boot = (optind < argc); |
if (optind < argc) { |
3547 |
|
hd_filename[0] = argv[optind++]; |
3548 |
|
} |
3549 |
|
|
3550 |
|
linux_boot = (kernel_filename != NULL); |
3551 |
|
|
3552 |
if (!linux_boot && hd_filename[0] == '\0') |
if (!linux_boot && hd_filename[0] == '\0') |
3553 |
help(); |
help(); |
3567 |
net_init(); |
net_init(); |
3568 |
|
|
3569 |
/* init the memory */ |
/* init the memory */ |
3570 |
tmpdir = getenv("VLTMPDIR"); |
tmpdir = getenv("QEMU_TMPDIR"); |
3571 |
if (!tmpdir) |
if (!tmpdir) |
3572 |
tmpdir = "/tmp"; |
tmpdir = "/tmp"; |
3573 |
snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir); |
snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir); |
3618 |
|
|
3619 |
if (linux_boot) { |
if (linux_boot) { |
3620 |
/* now we can load the kernel */ |
/* now we can load the kernel */ |
3621 |
ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); |
ret = load_kernel(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); |
3622 |
if (ret < 0) { |
if (ret < 0) { |
3623 |
fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); |
fprintf(stderr, "vl: could not load kernel '%s'\n", |
3624 |
|
kernel_filename); |
3625 |
exit(1); |
exit(1); |
3626 |
} |
} |
3627 |
|
|
3643 |
params->cl_magic = 0xA33F; |
params->cl_magic = 0xA33F; |
3644 |
params->cl_offset = params->commandline - (uint8_t *)params; |
params->cl_offset = params->commandline - (uint8_t *)params; |
3645 |
params->alt_mem_k = (phys_ram_size / 1024) - 1024; |
params->alt_mem_k = (phys_ram_size / 1024) - 1024; |
3646 |
for(i = optind + 1; i < argc; i++) { |
pstrcat(params->commandline, sizeof(params->commandline), kernel_cmdline); |
|
if (i != optind + 1) |
|
|
pstrcat(params->commandline, sizeof(params->commandline), " "); |
|
|
pstrcat(params->commandline, sizeof(params->commandline), argv[i]); |
|
|
} |
|
3647 |
params->loader_type = 0x01; |
params->loader_type = 0x01; |
3648 |
if (initrd_size > 0) { |
if (initrd_size > 0) { |
3649 |
params->initrd_start = INITRD_LOAD_ADDR; |
params->initrd_start = INITRD_LOAD_ADDR; |
3679 |
|
|
3680 |
} else { |
} else { |
3681 |
char buf[1024]; |
char buf[1024]; |
3682 |
|
|
3683 |
/* RAW PC boot */ |
/* RAW PC boot */ |
3684 |
|
|
3685 |
/* BIOS load */ |
/* BIOS load */ |
3719 |
} |
} |
3720 |
|
|
3721 |
/* terminal init */ |
/* terminal init */ |
3722 |
if (nodisp) { |
if (nographic) { |
3723 |
dumb_display_init(ds); |
dumb_display_init(ds); |
3724 |
} else { |
} else { |
3725 |
#ifdef CONFIG_SDL |
#ifdef CONFIG_SDL |
3726 |
sdl_display_init(ds); |
sdl_display_init(ds); |
|
/* SDL use the pthreads and they modify sigaction. We don't |
|
|
want that. */ |
|
|
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) |
|
|
#define sigaction __libc_sigaction |
|
|
#else |
|
|
#define sigaction __sigaction |
|
|
#endif |
|
3727 |
#else |
#else |
3728 |
dumb_display_init(ds); |
dumb_display_init(ds); |
3729 |
#endif |
#endif |