Commit a20dd508aa3895b2e5f4d4f255a4d6306b5e2631
1 parent
6180a181
simplified invocation - added automatic IDE disk geometry guessing to reuse old disk images directly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@392 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
113 additions
and
43 deletions
vl.c
@@ -44,7 +44,7 @@ | @@ -44,7 +44,7 @@ | ||
44 | #include <linux/if.h> | 44 | #include <linux/if.h> |
45 | #include <linux/if_tun.h> | 45 | #include <linux/if_tun.h> |
46 | 46 | ||
47 | -#include "cpu-i386.h" | 47 | +#include "cpu.h" |
48 | #include "disas.h" | 48 | #include "disas.h" |
49 | #include "thunk.h" | 49 | #include "thunk.h" |
50 | 50 | ||
@@ -216,7 +216,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; | @@ -216,7 +216,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; | ||
216 | BlockDriverState *bs_table[MAX_DISKS]; | 216 | BlockDriverState *bs_table[MAX_DISKS]; |
217 | int vga_ram_size; | 217 | int vga_ram_size; |
218 | static DisplayState display_state; | 218 | static DisplayState display_state; |
219 | -int nodisp; | 219 | +int nographic; |
220 | int term_inited; | 220 | int term_inited; |
221 | int64_t ticks_per_sec; | 221 | int64_t ticks_per_sec; |
222 | 222 | ||
@@ -2434,6 +2434,52 @@ void ide_reset(IDEState *s) | @@ -2434,6 +2434,52 @@ void ide_reset(IDEState *s) | ||
2434 | s->select = 0xa0; | 2434 | s->select = 0xa0; |
2435 | } | 2435 | } |
2436 | 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 | + | ||
2437 | void ide_init(void) | 2483 | void ide_init(void) |
2438 | { | 2484 | { |
2439 | IDEState *s; | 2485 | IDEState *s; |
@@ -2445,6 +2491,8 @@ void ide_init(void) | @@ -2445,6 +2491,8 @@ void ide_init(void) | ||
2445 | s->bs = bs_table[i]; | 2491 | s->bs = bs_table[i]; |
2446 | if (s->bs) { | 2492 | if (s->bs) { |
2447 | bdrv_get_geometry(s->bs, &nb_sectors); | 2493 | bdrv_get_geometry(s->bs, &nb_sectors); |
2494 | + s->nb_sectors = nb_sectors; | ||
2495 | + ide_guess_geometry(s); | ||
2448 | if (s->cylinders == 0) { | 2496 | if (s->cylinders == 0) { |
2449 | /* if no geometry, use a LBA compatible one */ | 2497 | /* if no geometry, use a LBA compatible one */ |
2450 | cylinders = nb_sectors / (16 * 63); | 2498 | cylinders = nb_sectors / (16 * 63); |
@@ -2456,7 +2504,6 @@ void ide_init(void) | @@ -2456,7 +2504,6 @@ void ide_init(void) | ||
2456 | s->heads = 16; | 2504 | s->heads = 16; |
2457 | s->sectors = 63; | 2505 | s->sectors = 63; |
2458 | } | 2506 | } |
2459 | - s->nb_sectors = nb_sectors; | ||
2460 | } | 2507 | } |
2461 | s->irq = 14; | 2508 | s->irq = 14; |
2462 | ide_reset(s); | 2509 | ide_reset(s); |
@@ -3136,7 +3183,10 @@ static void term_init(void) | @@ -3136,7 +3183,10 @@ static void term_init(void) | ||
3136 | tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP | 3183 | tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |
3137 | |INLCR|IGNCR|ICRNL|IXON); | 3184 | |INLCR|IGNCR|ICRNL|IXON); |
3138 | tty.c_oflag |= OPOST; | 3185 | tty.c_oflag |= OPOST; |
3139 | - tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); | 3186 | + tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); |
3187 | + /* if graphical mode, we allow Ctrl-C handling */ | ||
3188 | + if (nographic) | ||
3189 | + tty.c_lflag &= ~ISIG; | ||
3140 | tty.c_cflag &= ~(CSIZE|PARENB); | 3190 | tty.c_cflag &= ~(CSIZE|PARENB); |
3141 | tty.c_cflag |= CS8; | 3191 | tty.c_cflag |= CS8; |
3142 | tty.c_cc[VMIN] = 1; | 3192 | tty.c_cc[VMIN] = 1; |
@@ -3238,7 +3288,7 @@ int main_loop(void *opaque) | @@ -3238,7 +3288,7 @@ int main_loop(void *opaque) | ||
3238 | uint8_t ch; | 3288 | uint8_t ch; |
3239 | CPUState *env = global_env; | 3289 | CPUState *env = global_env; |
3240 | 3290 | ||
3241 | - if (nodisp && !term_inited) { | 3291 | + if (!term_inited) { |
3242 | /* initialize terminal only there so that the user has a | 3292 | /* initialize terminal only there so that the user has a |
3243 | chance to stop QEMU with Ctrl-C before the gdb connection | 3293 | chance to stop QEMU with Ctrl-C before the gdb connection |
3244 | is launched */ | 3294 | is launched */ |
@@ -3328,26 +3378,30 @@ int main_loop(void *opaque) | @@ -3328,26 +3378,30 @@ int main_loop(void *opaque) | ||
3328 | 3378 | ||
3329 | void help(void) | 3379 | void help(void) |
3330 | { | 3380 | { |
3331 | - printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" | ||
3332 | - "usage: vl [options] [bzImage [kernel parameters...]]\n" | 3381 | + printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
3382 | + "usage: qemu [options] [disk_image]\n" | ||
3333 | "\n" | 3383 | "\n" |
3334 | - "'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" | ||
3335 | - "to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" | 3384 | + "'disk_image' is a raw hard image image for IDE hard disk 0\n" |
3336 | "\n" | 3385 | "\n" |
3337 | - "General options:\n" | ||
3338 | - "-initrd file use 'file' as initial ram disk\n" | ||
3339 | - "-hda file use 'file' as hard disk 0 image\n" | ||
3340 | - "-hdb file use 'file' as hard disk 1 image\n" | ||
3341 | - "-snapshot write to temporary files instead of disk image files\n" | ||
3342 | - "-m megs set virtual RAM size to megs MB\n" | ||
3343 | - "-n script set network init script [default=%s]\n" | 3386 | + "Standard options:\n" |
3387 | + "-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" | ||
3394 | + "Linux boot specific (does not require PC BIOS):\n" | ||
3395 | + "-kernel bzImage use 'bzImage' as kernel image\n" | ||
3396 | + "-append cmdline use 'cmdline' as kernel command line\n" | ||
3397 | + "-initrd file use 'file' as initial ram disk\n" | ||
3344 | "\n" | 3398 | "\n" |
3345 | "Debug/Expert options:\n" | 3399 | "Debug/Expert options:\n" |
3346 | - "-s wait gdb connection to port %d\n" | ||
3347 | - "-p port change gdb connection port\n" | ||
3348 | - "-d output log in /tmp/vl.log\n" | ||
3349 | - "-hdachs c,h,s force hard disk 0 geometry for non LBA disk images\n" | ||
3350 | - "-L path set the directory for the BIOS and VGA BIOS\n" | 3400 | + "-s wait gdb connection to port %d\n" |
3401 | + "-p port change gdb connection port\n" | ||
3402 | + "-d output log in /tmp/vl.log\n" | ||
3403 | + "-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" | ||
3351 | "\n" | 3405 | "\n" |
3352 | "During emulation, use C-a h to get terminal commands:\n", | 3406 | "During emulation, use C-a h to get terminal commands:\n", |
3353 | DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); | 3407 | DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
@@ -3361,10 +3415,24 @@ struct option long_options[] = { | @@ -3361,10 +3415,24 @@ struct option long_options[] = { | ||
3361 | { "hdb", 1, NULL, 0, }, | 3415 | { "hdb", 1, NULL, 0, }, |
3362 | { "snapshot", 0, NULL, 0, }, | 3416 | { "snapshot", 0, NULL, 0, }, |
3363 | { "hdachs", 1, NULL, 0, }, | 3417 | { "hdachs", 1, NULL, 0, }, |
3364 | - { "nodisp", 0, NULL, 0, }, | 3418 | + { "nographic", 0, NULL, 0, }, |
3419 | + { "kernel", 1, NULL, 0, }, | ||
3420 | + { "append", 1, NULL, 0, }, | ||
3365 | { NULL, 0, NULL, 0 }, | 3421 | { NULL, 0, NULL, 0 }, |
3366 | }; | 3422 | }; |
3367 | 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 | + | ||
3368 | int main(int argc, char **argv) | 3436 | int main(int argc, char **argv) |
3369 | { | 3437 | { |
3370 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; | 3438 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
@@ -3375,6 +3443,7 @@ int main(int argc, char **argv) | @@ -3375,6 +3443,7 @@ int main(int argc, char **argv) | ||
3375 | CPUX86State *env; | 3443 | CPUX86State *env; |
3376 | const char *tmpdir, *initrd_filename; | 3444 | const char *tmpdir, *initrd_filename; |
3377 | const char *hd_filename[MAX_DISKS]; | 3445 | const char *hd_filename[MAX_DISKS]; |
3446 | + const char *kernel_filename, *kernel_cmdline; | ||
3378 | DisplayState *ds = &display_state; | 3447 | DisplayState *ds = &display_state; |
3379 | 3448 | ||
3380 | /* we never want that malloc() uses mmap() */ | 3449 | /* we never want that malloc() uses mmap() */ |
@@ -3388,8 +3457,9 @@ int main(int argc, char **argv) | @@ -3388,8 +3457,9 @@ int main(int argc, char **argv) | ||
3388 | use_gdbstub = 0; | 3457 | use_gdbstub = 0; |
3389 | gdbstub_port = DEFAULT_GDBSTUB_PORT; | 3458 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
3390 | snapshot = 0; | 3459 | snapshot = 0; |
3391 | - linux_boot = 0; | ||
3392 | - nodisp = 0; | 3460 | + nographic = 0; |
3461 | + kernel_filename = NULL; | ||
3462 | + kernel_cmdline = ""; | ||
3393 | for(;;) { | 3463 | for(;;) { |
3394 | c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); | 3464 | c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
3395 | if (c == -1) | 3465 | if (c == -1) |
@@ -3432,7 +3502,13 @@ int main(int argc, char **argv) | @@ -3432,7 +3502,13 @@ int main(int argc, char **argv) | ||
3432 | } | 3502 | } |
3433 | break; | 3503 | break; |
3434 | case 5: | 3504 | case 5: |
3435 | - nodisp = 1; | 3505 | + nographic = 1; |
3506 | + break; | ||
3507 | + case 6: | ||
3508 | + kernel_filename = optarg; | ||
3509 | + break; | ||
3510 | + case 7: | ||
3511 | + kernel_cmdline = optarg; | ||
3436 | break; | 3512 | break; |
3437 | } | 3513 | } |
3438 | break; | 3514 | break; |
@@ -3467,7 +3543,11 @@ int main(int argc, char **argv) | @@ -3467,7 +3543,11 @@ int main(int argc, char **argv) | ||
3467 | } | 3543 | } |
3468 | } | 3544 | } |
3469 | 3545 | ||
3470 | - linux_boot = (optind < argc); | 3546 | + if (optind < argc) { |
3547 | + hd_filename[0] = argv[optind++]; | ||
3548 | + } | ||
3549 | + | ||
3550 | + linux_boot = (kernel_filename != NULL); | ||
3471 | 3551 | ||
3472 | if (!linux_boot && hd_filename[0] == '\0') | 3552 | if (!linux_boot && hd_filename[0] == '\0') |
3473 | help(); | 3553 | help(); |
@@ -3487,7 +3567,7 @@ int main(int argc, char **argv) | @@ -3487,7 +3567,7 @@ int main(int argc, char **argv) | ||
3487 | net_init(); | 3567 | net_init(); |
3488 | 3568 | ||
3489 | /* init the memory */ | 3569 | /* init the memory */ |
3490 | - tmpdir = getenv("VLTMPDIR"); | 3570 | + tmpdir = getenv("QEMU_TMPDIR"); |
3491 | if (!tmpdir) | 3571 | if (!tmpdir) |
3492 | tmpdir = "/tmp"; | 3572 | tmpdir = "/tmp"; |
3493 | snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir); | 3573 | snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir); |
@@ -3538,9 +3618,10 @@ int main(int argc, char **argv) | @@ -3538,9 +3618,10 @@ int main(int argc, char **argv) | ||
3538 | 3618 | ||
3539 | if (linux_boot) { | 3619 | if (linux_boot) { |
3540 | /* now we can load the kernel */ | 3620 | /* now we can load the kernel */ |
3541 | - ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); | 3621 | + ret = load_kernel(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); |
3542 | if (ret < 0) { | 3622 | if (ret < 0) { |
3543 | - fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); | 3623 | + fprintf(stderr, "vl: could not load kernel '%s'\n", |
3624 | + kernel_filename); | ||
3544 | exit(1); | 3625 | exit(1); |
3545 | } | 3626 | } |
3546 | 3627 | ||
@@ -3562,11 +3643,7 @@ int main(int argc, char **argv) | @@ -3562,11 +3643,7 @@ int main(int argc, char **argv) | ||
3562 | params->cl_magic = 0xA33F; | 3643 | params->cl_magic = 0xA33F; |
3563 | params->cl_offset = params->commandline - (uint8_t *)params; | 3644 | params->cl_offset = params->commandline - (uint8_t *)params; |
3564 | params->alt_mem_k = (phys_ram_size / 1024) - 1024; | 3645 | params->alt_mem_k = (phys_ram_size / 1024) - 1024; |
3565 | - for(i = optind + 1; i < argc; i++) { | ||
3566 | - if (i != optind + 1) | ||
3567 | - pstrcat(params->commandline, sizeof(params->commandline), " "); | ||
3568 | - pstrcat(params->commandline, sizeof(params->commandline), argv[i]); | ||
3569 | - } | 3646 | + pstrcat(params->commandline, sizeof(params->commandline), kernel_cmdline); |
3570 | params->loader_type = 0x01; | 3647 | params->loader_type = 0x01; |
3571 | if (initrd_size > 0) { | 3648 | if (initrd_size > 0) { |
3572 | params->initrd_start = INITRD_LOAD_ADDR; | 3649 | params->initrd_start = INITRD_LOAD_ADDR; |
@@ -3602,7 +3679,7 @@ int main(int argc, char **argv) | @@ -3602,7 +3679,7 @@ int main(int argc, char **argv) | ||
3602 | 3679 | ||
3603 | } else { | 3680 | } else { |
3604 | char buf[1024]; | 3681 | char buf[1024]; |
3605 | - | 3682 | + |
3606 | /* RAW PC boot */ | 3683 | /* RAW PC boot */ |
3607 | 3684 | ||
3608 | /* BIOS load */ | 3685 | /* BIOS load */ |
@@ -3642,18 +3719,11 @@ int main(int argc, char **argv) | @@ -3642,18 +3719,11 @@ int main(int argc, char **argv) | ||
3642 | } | 3719 | } |
3643 | 3720 | ||
3644 | /* terminal init */ | 3721 | /* terminal init */ |
3645 | - if (nodisp) { | 3722 | + if (nographic) { |
3646 | dumb_display_init(ds); | 3723 | dumb_display_init(ds); |
3647 | } else { | 3724 | } else { |
3648 | #ifdef CONFIG_SDL | 3725 | #ifdef CONFIG_SDL |
3649 | sdl_display_init(ds); | 3726 | sdl_display_init(ds); |
3650 | - /* SDL use the pthreads and they modify sigaction. We don't | ||
3651 | - want that. */ | ||
3652 | -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) | ||
3653 | -#define sigaction __libc_sigaction | ||
3654 | -#else | ||
3655 | -#define sigaction __sigaction | ||
3656 | -#endif | ||
3657 | #else | 3727 | #else |
3658 | dumb_display_init(ds); | 3728 | dumb_display_init(ds); |
3659 | #endif | 3729 | #endif |