/* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
to store the VM snapshots */
BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
+BlockDriverState *sd_bdrv;
/* point to the block driver where the snapshots are managed */
BlockDriverState *bs_snapshots;
int vga_ram_size;
int vm_running;
int rtc_utc = 1;
int cirrus_vga_enabled = 1;
+int vmsvga_enabled = 0;
#ifdef TARGET_SPARC
int graphic_width = 1024;
int graphic_height = 768;
int nb_option_roms;
int semihosting_enabled = 0;
int autostart = 1;
+const char *qemu_name;
/***********************************************************/
/* x86 ISA bus support */
uint32_t default_ioport_readb(void *opaque, uint32_t address)
{
#ifdef DEBUG_UNUSED_IOPORT
- fprintf(stderr, "inb: port=0x%04x\n", address);
+ fprintf(stderr, "unused inb: port=0x%04x\n", address);
#endif
return 0xff;
}
void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
{
#ifdef DEBUG_UNUSED_IOPORT
- fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
+ fprintf(stderr, "unused outb: port=0x%04x data=0x%02x\n", address, data);
#endif
}
uint32_t default_ioport_readl(void *opaque, uint32_t address)
{
#ifdef DEBUG_UNUSED_IOPORT
- fprintf(stderr, "inl: port=0x%04x\n", address);
+ fprintf(stderr, "unused inl: port=0x%04x\n", address);
#endif
return 0xffffffff;
}
void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
{
#ifdef DEBUG_UNUSED_IOPORT
- fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
+ fprintf(stderr, "unused outl: port=0x%04x data=0x%02x\n", address, data);
#endif
}
return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
}
+void (*kbd_mouse_set)(int x, int y, int on) = NULL;
+void (*kbd_cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
+ uint8_t *image, uint8_t *mask) = NULL;
+
void do_info_mice(void)
{
QEMUPutMouseEntry *cursor;
/* MUX driver for serial I/O splitting */
static int term_timestamps;
static int64_t term_timestamps_start;
-#define MAX_MUX 2
+#define MAX_MUX 4
typedef struct {
IOCanRWHandler *chr_can_read[MAX_MUX];
IOReadHandler *chr_read[MAX_MUX];
if (err == EINTR || err == EWOULDBLOCK) {
} else if (err == EINPROGRESS) {
break;
+#ifdef _WIN32
+ } else if (err == WSAEALREADY) {
+ break;
+#endif
} else {
goto fail;
}
pid = fork();
if (pid >= 0) {
if (pid == 0) {
+ int open_max = sysconf (_SC_OPEN_MAX), i;
+ for (i = 0; i < open_max; i++)
+ if (i != STDIN_FILENO &&
+ i != STDOUT_FILENO &&
+ i != STDERR_FILENO &&
+ i != fd)
+ close(i);
+
parg = args;
*parg++ = (char *)setup_script;
*parg++ = ifname;
if (err == EINTR || err == EWOULDBLOCK) {
} else if (err == EINPROGRESS) {
break;
+#ifdef _WIN32
+ } else if (err == WSAEALREADY) {
+ break;
+#endif
} else {
perror("connect");
closesocket(fd);
}
/***********************************************************/
-/* pid file */
-
-static char *pid_filename;
-
-/* Remove PID file. Called on normal exit */
-
-static void remove_pidfile(void)
-{
- unlink (pid_filename);
-}
-
-static void create_pidfile(const char *filename)
-{
- struct stat pidstat;
- FILE *f;
-
- /* Try to write our PID to the named file */
- if (stat(filename, &pidstat) < 0) {
- if (errno == ENOENT) {
- if ((f = fopen (filename, "w")) == NULL) {
- perror("Opening pidfile");
- exit(1);
- }
- fprintf(f, "%d\n", getpid());
- fclose(f);
- pid_filename = qemu_strdup(filename);
- if (!pid_filename) {
- fprintf(stderr, "Could not save PID filename");
- exit(1);
- }
- atexit(remove_pidfile);
- }
- } else {
- fprintf(stderr, "%s already exists. Remove it and try again.\n",
- filename);
- exit(1);
- }
-}
-
-/***********************************************************/
/* dumb display */
static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
IOCanRWHandler *fd_read_poll;
IOHandler *fd_read;
IOHandler *fd_write;
+ int deleted;
void *opaque;
/* temporary data */
struct pollfd *ufd;
if (ioh == NULL)
break;
if (ioh->fd == fd) {
- *pioh = ioh->next;
- qemu_free(ioh);
+ ioh->deleted = 1;
break;
}
pioh = &ioh->next;
ioh->fd_read = fd_read;
ioh->fd_write = fd_write;
ioh->opaque = opaque;
+ ioh->deleted = 0;
}
return 0;
}
void main_loop_wait(int timeout)
{
- IOHandlerRecord *ioh, *ioh_next;
+ IOHandlerRecord *ioh;
fd_set rfds, wfds, xfds;
int ret, nfds;
struct timeval tv;
FD_ZERO(&wfds);
FD_ZERO(&xfds);
for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
+ if (ioh->deleted)
+ continue;
if (ioh->fd_read &&
(!ioh->fd_read_poll ||
ioh->fd_read_poll(ioh->opaque) != 0)) {
#endif
ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
if (ret > 0) {
- /* XXX: better handling of removal */
- for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
- ioh_next = ioh->next;
+ IOHandlerRecord **pioh;
+
+ for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
+ if (ioh->deleted)
+ continue;
if (FD_ISSET(ioh->fd, &rfds)) {
ioh->fd_read(ioh->opaque);
}
ioh->fd_write(ioh->opaque);
}
}
+
+ /* remove deleted IO handlers */
+ pioh = &first_io_handler;
+ while (*pioh) {
+ ioh = *pioh;
+ if (ioh->deleted) {
+ *pioh = ioh->next;
+ qemu_free(ioh);
+ } else
+ pioh = &ioh->next;
+ }
}
#if defined(CONFIG_SLIRP)
if (slirp_inited) {
#ifdef CONFIG_PROFILER
qemu_time += profile_getclock() - ti;
#endif
+ if (ret == EXCP_HLT) {
+ /* Give the next CPU a chance to run. */
+ cur_cpu = env;
+ continue;
+ }
if (ret != EXCP_HALTED)
break;
/* all CPUs are halted ? */
- if (env == cur_cpu) {
- ret = EXCP_HLT;
+ if (env == cur_cpu)
break;
- }
}
cur_cpu = env;
if (ret == EXCP_DEBUG) {
vm_stop(EXCP_DEBUG);
}
- /* if hlt instruction, we wait until the next IRQ */
+ /* If all cpus are halted then wait until the next IRQ */
/* XXX: use timeout computed from timers */
- if (ret == EXCP_HLT)
+ if (ret == EXCP_HALTED)
timeout = 10;
else
timeout = 0;
"\n"
"Standard options:\n"
"-M machine select emulated machine (-M ? for list)\n"
+ "-cpu cpu select CPU (-cpu ? for list)\n"
"-fda/-fdb file use 'file' as floppy disk 0/1 image\n"
"-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
+ "-sd file use 'file' as SecureDigital card image\n"
"-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
"-snapshot write to temporary files instead of disk image files\n"
#ifdef CONFIG_SDL
#if defined(TARGET_PPC) || defined(TARGET_SPARC)
"-g WxH[xDEPTH] Set the initial graphical resolution and depth\n"
#endif
+ "-name string set the name of the guest\n"
"\n"
"Network options:\n"
"-net nic[,vlan=n][,macaddr=addr][,model=type]\n"
" is provided, the default is '-net nic -net user'\n"
"\n"
#ifdef CONFIG_SLIRP
- "-tftp prefix allow tftp access to files starting with prefix [-net user]\n"
+ "-tftp dir allow tftp access to files in dir [-net user]\n"
+ "-bootp file advertise file in BOOTP replies\n"
#ifndef _WIN32
"-smb dir allow SMB access to files in 'dir' [-net user]\n"
#endif
"-parallel dev redirect the parallel port to char device 'dev'\n"
"-pidfile file Write PID to 'file'\n"
"-S freeze CPU at startup (use 'c' to start execution)\n"
- "-s wait gdb connection to port %d\n"
- "-p port change gdb connection port\n"
+ "-s wait gdb connection to port\n"
+ "-p port set gdb connection port [default=%s]\n"
"-d item1,... output log to %s (use -d ? for a list of log items)\n"
"-hdachs c,h,s[,t] force hard disk 0 physical geometry and the optional BIOS\n"
" translation (t=none or lba) (usually qemu can guess them)\n"
QEMU_OPTION_h,
QEMU_OPTION_M,
+ QEMU_OPTION_cpu,
QEMU_OPTION_fda,
QEMU_OPTION_fdb,
QEMU_OPTION_hda,
QEMU_OPTION_hdc,
QEMU_OPTION_hdd,
QEMU_OPTION_cdrom,
+ QEMU_OPTION_sd,
QEMU_OPTION_boot,
QEMU_OPTION_snapshot,
#ifdef TARGET_I386
QEMU_OPTION_net,
QEMU_OPTION_tftp,
+ QEMU_OPTION_bootp,
QEMU_OPTION_smb,
QEMU_OPTION_redir,
QEMU_OPTION_k,
QEMU_OPTION_localtime,
QEMU_OPTION_cirrusvga,
+ QEMU_OPTION_vmsvga,
QEMU_OPTION_g,
QEMU_OPTION_std_vga,
QEMU_OPTION_echr,
QEMU_OPTION_no_reboot,
QEMU_OPTION_daemonize,
QEMU_OPTION_option_rom,
- QEMU_OPTION_semihosting
+ QEMU_OPTION_semihosting,
+ QEMU_OPTION_name,
};
typedef struct QEMUOption {
{ "help", 0, QEMU_OPTION_h },
{ "M", HAS_ARG, QEMU_OPTION_M },
+ { "cpu", HAS_ARG, QEMU_OPTION_cpu },
{ "fda", HAS_ARG, QEMU_OPTION_fda },
{ "fdb", HAS_ARG, QEMU_OPTION_fdb },
{ "hda", HAS_ARG, QEMU_OPTION_hda },
{ "hdc", HAS_ARG, QEMU_OPTION_hdc },
{ "hdd", HAS_ARG, QEMU_OPTION_hdd },
{ "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
+ { "sd", HAS_ARG, QEMU_OPTION_sd },
{ "boot", HAS_ARG, QEMU_OPTION_boot },
{ "snapshot", 0, QEMU_OPTION_snapshot },
#ifdef TARGET_I386
{ "net", HAS_ARG, QEMU_OPTION_net},
#ifdef CONFIG_SLIRP
{ "tftp", HAS_ARG, QEMU_OPTION_tftp },
+ { "bootp", HAS_ARG, QEMU_OPTION_bootp },
#ifndef _WIN32
{ "smb", HAS_ARG, QEMU_OPTION_smb },
#endif
/* temporary options */
{ "usb", 0, QEMU_OPTION_usb },
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
+ { "vmwarevga", 0, QEMU_OPTION_vmsvga },
{ "no-acpi", 0, QEMU_OPTION_no_acpi },
{ "no-reboot", 0, QEMU_OPTION_no_reboot },
{ "daemonize", 0, QEMU_OPTION_daemonize },
#if defined(TARGET_ARM)
{ "semihosting", 0, QEMU_OPTION_semihosting },
#endif
+ { "name", HAS_ARG, QEMU_OPTION_name },
{ NULL },
};
#ifdef TARGET_SPARC64
qemu_register_machine(&sun4u_machine);
#else
- qemu_register_machine(&sun4m_machine);
+ qemu_register_machine(&ss5_machine);
+ qemu_register_machine(&ss10_machine);
#endif
#elif defined(TARGET_ARM)
- qemu_register_machine(&integratorcp926_machine);
- qemu_register_machine(&integratorcp1026_machine);
+ qemu_register_machine(&integratorcp_machine);
qemu_register_machine(&versatilepb_machine);
qemu_register_machine(&versatileab_machine);
qemu_register_machine(&realview_machine);
#elif defined(TARGET_SH4)
qemu_register_machine(&shix_machine);
+#elif defined(TARGET_ALPHA)
+ /* XXX: TODO */
#else
#error unsupported CPU
#endif
int main(int argc, char **argv)
{
#ifdef CONFIG_GDBSTUB
- int use_gdbstub, gdbstub_port;
+ int use_gdbstub;
+ const char *gdbstub_port;
#endif
int i, cdrom_index;
int snapshot, linux_boot;
const char *initrd_filename;
const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
+ const char *sd_filename;
const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state;
int cyls, heads, secs, translation;
int parallel_device_index;
const char *loadvm = NULL;
QEMUMachine *machine;
+ const char *cpu_model;
char usb_devices[MAX_USB_CMDLINE][128];
int usb_devices_index;
int fds[2];
+ const char *pid_file = NULL;
LIST_INIT (&vm_change_state_head);
#ifndef _WIN32
register_machines();
machine = first_machine;
+ cpu_model = NULL;
initrd_filename = NULL;
for(i = 0; i < MAX_FD; i++)
fd_filename[i] = NULL;
for(i = 0; i < MAX_DISKS; i++)
hd_filename[i] = NULL;
+ sd_filename = NULL;
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
vga_ram_size = VGA_RAM_SIZE;
#ifdef CONFIG_GDBSTUB
exit(1);
}
break;
+ case QEMU_OPTION_cpu:
+ /* hw initialization will check this */
+ if (optarg[0] == '?') {
+#if defined(TARGET_PPC)
+ ppc_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_ARM)
+ arm_cpu_list();
+#elif defined(TARGET_MIPS)
+ mips_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_SPARC)
+ sparc_cpu_list(stdout, &fprintf);
+#endif
+ exit(1);
+ } else {
+ cpu_model = optarg;
+ }
+ break;
case QEMU_OPTION_initrd:
initrd_filename = optarg;
break;
cdrom_index = -1;
}
break;
+ case QEMU_OPTION_sd:
+ sd_filename = optarg;
+ break;
case QEMU_OPTION_snapshot:
snapshot = 1;
break;
break;
case QEMU_OPTION_nographic:
pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
+ pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null");
pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
nographic = 1;
break;
case QEMU_OPTION_tftp:
tftp_prefix = optarg;
break;
+ case QEMU_OPTION_bootp:
+ bootp_filename = optarg;
+ break;
#ifndef _WIN32
case QEMU_OPTION_smb:
net_slirp_smb(optarg);
use_gdbstub = 1;
break;
case QEMU_OPTION_p:
- gdbstub_port = atoi(optarg);
+ gdbstub_port = optarg;
break;
#endif
case QEMU_OPTION_L:
break;
case QEMU_OPTION_cirrusvga:
cirrus_vga_enabled = 1;
+ vmsvga_enabled = 0;
+ break;
+ case QEMU_OPTION_vmsvga:
+ cirrus_vga_enabled = 0;
+ vmsvga_enabled = 1;
break;
case QEMU_OPTION_std_vga:
cirrus_vga_enabled = 0;
+ vmsvga_enabled = 0;
break;
case QEMU_OPTION_g:
{
break;
#endif
case QEMU_OPTION_pidfile:
- create_pidfile(optarg);
+ pid_file = optarg;
break;
#ifdef TARGET_I386
case QEMU_OPTION_win2k_hack:
case QEMU_OPTION_semihosting:
semihosting_enabled = 1;
break;
+ case QEMU_OPTION_name:
+ qemu_name = optarg;
+ break;
}
}
}
close(fds[1]);
again:
- len = read(fds[0], &status, 1);
- if (len == -1 && (errno == EINTR))
- goto again;
-
- if (len != 1 || status != 0)
- exit(1);
- else
- exit(0);
+ len = read(fds[0], &status, 1);
+ if (len == -1 && (errno == EINTR))
+ goto again;
+
+ if (len != 1)
+ exit(1);
+ else if (status == 1) {
+ fprintf(stderr, "Could not acquire pidfile\n");
+ exit(1);
+ } else
+ exit(0);
} else if (pid < 0)
- exit(1);
+ exit(1);
setsid();
}
#endif
+ if (pid_file && qemu_create_pidfile(pid_file) != 0) {
+ if (daemonize) {
+ uint8_t status = 1;
+ write(fds[1], &status, 1);
+ } else
+ fprintf(stderr, "Could not acquire pid file\n");
+ exit(1);
+ }
+
#ifdef USE_KQEMU
if (smp_cpus > 1)
kqemu_allowed = 0;
fd_table[i] = bdrv_new(buf);
bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
}
- if (fd_filename[i] != '\0') {
+ if (fd_filename[i][0] != '\0') {
if (bdrv_open(fd_table[i], fd_filename[i],
snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
}
}
+ sd_bdrv = bdrv_new ("sd");
+ /* FIXME: This isn't really a floppy, but it's a reasonable
+ approximation. */
+ bdrv_set_type_hint(sd_bdrv, BDRV_TYPE_FLOPPY);
+ if (sd_filename) {
+ if (bdrv_open(sd_bdrv, sd_filename,
+ snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
+ fprintf(stderr, "qemu: could not open SD card image %s\n",
+ sd_filename);
+ }
+ }
+
register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
machine->init(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline, initrd_filename);
+ kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
/* init USB devices */
if (usb_enabled) {
if (use_gdbstub) {
/* XXX: use standard host:port notation and modify options
accordingly. */
- if (gdbserver_start_port(gdbstub_port) < 0) {
- fprintf(stderr, "qemu: could not open gdbstub device on port '%d'\n",
+ if (gdbserver_start(gdbstub_port) < 0) {
+ fprintf(stderr, "qemu: could not open gdbstub device on port '%s'\n",
gdbstub_port);
exit(1);
}