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 | 44 | #include <linux/if.h> |
45 | 45 | #include <linux/if_tun.h> |
46 | 46 | |
47 | -#include "cpu-i386.h" | |
47 | +#include "cpu.h" | |
48 | 48 | #include "disas.h" |
49 | 49 | #include "thunk.h" |
50 | 50 | |
... | ... | @@ -216,7 +216,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
216 | 216 | BlockDriverState *bs_table[MAX_DISKS]; |
217 | 217 | int vga_ram_size; |
218 | 218 | static DisplayState display_state; |
219 | -int nodisp; | |
219 | +int nographic; | |
220 | 220 | int term_inited; |
221 | 221 | int64_t ticks_per_sec; |
222 | 222 | |
... | ... | @@ -2434,6 +2434,52 @@ void ide_reset(IDEState *s) |
2434 | 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 | 2483 | void ide_init(void) |
2438 | 2484 | { |
2439 | 2485 | IDEState *s; |
... | ... | @@ -2445,6 +2491,8 @@ void ide_init(void) |
2445 | 2491 | s->bs = bs_table[i]; |
2446 | 2492 | if (s->bs) { |
2447 | 2493 | bdrv_get_geometry(s->bs, &nb_sectors); |
2494 | + s->nb_sectors = nb_sectors; | |
2495 | + ide_guess_geometry(s); | |
2448 | 2496 | if (s->cylinders == 0) { |
2449 | 2497 | /* if no geometry, use a LBA compatible one */ |
2450 | 2498 | cylinders = nb_sectors / (16 * 63); |
... | ... | @@ -2456,7 +2504,6 @@ void ide_init(void) |
2456 | 2504 | s->heads = 16; |
2457 | 2505 | s->sectors = 63; |
2458 | 2506 | } |
2459 | - s->nb_sectors = nb_sectors; | |
2460 | 2507 | } |
2461 | 2508 | s->irq = 14; |
2462 | 2509 | ide_reset(s); |
... | ... | @@ -3136,7 +3183,10 @@ static void term_init(void) |
3136 | 3183 | tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |
3137 | 3184 | |INLCR|IGNCR|ICRNL|IXON); |
3138 | 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 | 3190 | tty.c_cflag &= ~(CSIZE|PARENB); |
3141 | 3191 | tty.c_cflag |= CS8; |
3142 | 3192 | tty.c_cc[VMIN] = 1; |
... | ... | @@ -3238,7 +3288,7 @@ int main_loop(void *opaque) |
3238 | 3288 | uint8_t ch; |
3239 | 3289 | CPUState *env = global_env; |
3240 | 3290 | |
3241 | - if (nodisp && !term_inited) { | |
3291 | + if (!term_inited) { | |
3242 | 3292 | /* initialize terminal only there so that the user has a |
3243 | 3293 | chance to stop QEMU with Ctrl-C before the gdb connection |
3244 | 3294 | is launched */ |
... | ... | @@ -3328,26 +3378,30 @@ int main_loop(void *opaque) |
3328 | 3378 | |
3329 | 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 | 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 | 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 | 3398 | "\n" |
3345 | 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 | 3405 | "\n" |
3352 | 3406 | "During emulation, use C-a h to get terminal commands:\n", |
3353 | 3407 | DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
... | ... | @@ -3361,10 +3415,24 @@ struct option long_options[] = { |
3361 | 3415 | { "hdb", 1, NULL, 0, }, |
3362 | 3416 | { "snapshot", 0, NULL, 0, }, |
3363 | 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 | 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 | 3436 | int main(int argc, char **argv) |
3369 | 3437 | { |
3370 | 3438 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
... | ... | @@ -3375,6 +3443,7 @@ int main(int argc, char **argv) |
3375 | 3443 | CPUX86State *env; |
3376 | 3444 | const char *tmpdir, *initrd_filename; |
3377 | 3445 | const char *hd_filename[MAX_DISKS]; |
3446 | + const char *kernel_filename, *kernel_cmdline; | |
3378 | 3447 | DisplayState *ds = &display_state; |
3379 | 3448 | |
3380 | 3449 | /* we never want that malloc() uses mmap() */ |
... | ... | @@ -3388,8 +3457,9 @@ int main(int argc, char **argv) |
3388 | 3457 | use_gdbstub = 0; |
3389 | 3458 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
3390 | 3459 | snapshot = 0; |
3391 | - linux_boot = 0; | |
3392 | - nodisp = 0; | |
3460 | + nographic = 0; | |
3461 | + kernel_filename = NULL; | |
3462 | + kernel_cmdline = ""; | |
3393 | 3463 | for(;;) { |
3394 | 3464 | c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
3395 | 3465 | if (c == -1) |
... | ... | @@ -3432,7 +3502,13 @@ int main(int argc, char **argv) |
3432 | 3502 | } |
3433 | 3503 | break; |
3434 | 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 | 3512 | break; |
3437 | 3513 | } |
3438 | 3514 | break; |
... | ... | @@ -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 | 3552 | if (!linux_boot && hd_filename[0] == '\0') |
3473 | 3553 | help(); |
... | ... | @@ -3487,7 +3567,7 @@ int main(int argc, char **argv) |
3487 | 3567 | net_init(); |
3488 | 3568 | |
3489 | 3569 | /* init the memory */ |
3490 | - tmpdir = getenv("VLTMPDIR"); | |
3570 | + tmpdir = getenv("QEMU_TMPDIR"); | |
3491 | 3571 | if (!tmpdir) |
3492 | 3572 | tmpdir = "/tmp"; |
3493 | 3573 | snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir); |
... | ... | @@ -3538,9 +3618,10 @@ int main(int argc, char **argv) |
3538 | 3618 | |
3539 | 3619 | if (linux_boot) { |
3540 | 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 | 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 | 3625 | exit(1); |
3545 | 3626 | } |
3546 | 3627 | |
... | ... | @@ -3562,11 +3643,7 @@ int main(int argc, char **argv) |
3562 | 3643 | params->cl_magic = 0xA33F; |
3563 | 3644 | params->cl_offset = params->commandline - (uint8_t *)params; |
3564 | 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 | 3647 | params->loader_type = 0x01; |
3571 | 3648 | if (initrd_size > 0) { |
3572 | 3649 | params->initrd_start = INITRD_LOAD_ADDR; |
... | ... | @@ -3602,7 +3679,7 @@ int main(int argc, char **argv) |
3602 | 3679 | |
3603 | 3680 | } else { |
3604 | 3681 | char buf[1024]; |
3605 | - | |
3682 | + | |
3606 | 3683 | /* RAW PC boot */ |
3607 | 3684 | |
3608 | 3685 | /* BIOS load */ |
... | ... | @@ -3642,18 +3719,11 @@ int main(int argc, char **argv) |
3642 | 3719 | } |
3643 | 3720 | |
3644 | 3721 | /* terminal init */ |
3645 | - if (nodisp) { | |
3722 | + if (nographic) { | |
3646 | 3723 | dumb_display_init(ds); |
3647 | 3724 | } else { |
3648 | 3725 | #ifdef CONFIG_SDL |
3649 | 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 | 3727 | #else |
3658 | 3728 | dumb_display_init(ds); |
3659 | 3729 | #endif | ... | ... |