/*
* QEMU System Emulator
*
- * Copyright (c) 2003-2006 Fabrice Bellard
+ * Copyright (c) 2003-2007 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
#include <malloc.h>
#include <linux/rtc.h>
#include <linux/ppdev.h>
+#else
+#include <sys/stat.h>
+#include <sys/ethernet.h>
+#include <sys/sockio.h>
+#include <arpa/inet.h>
+#include <netinet/arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h> // must come after ip.h
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include <syslog.h>
+#include <stropts.h>
#endif
#endif
#endif
/* XXX: use a two level table to limit memory usage */
#define MAX_IOPORTS 65536
-#define DISK_OPTIONS_SIZE 256
-
const char *bios_dir = CONFIG_QEMU_SHAREDIR;
char phys_ram_file[1024];
void *ioport_opaque[MAX_IOPORTS];
BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
/* point to the block driver where the snapshots are managed */
BlockDriverState *bs_snapshots;
-BlockDriverState *bs_scsi_table[MAX_SCSI_DISKS];
-SCSIDiskInfo scsi_disks_info[MAX_SCSI_DISKS];
-int scsi_hba_lsi; /* Count of scsi disks/cdrom using this lsi adapter */
int vga_ram_size;
-int bios_size;
static DisplayState display_state;
int nographic;
const char* keyboard_layout = NULL;
int daemonize = 0;
const char *option_rom[MAX_OPTION_ROMS];
int nb_option_roms;
+int semihosting_enabled = 0;
+int autostart = 1;
/***********************************************************/
/* x86 ISA bus support */
/***********************************************************/
-void pstrcpy(char *buf, int buf_size, const char *str)
-{
- int c;
- char *q = buf;
-
- if (buf_size <= 0)
- return;
-
- for(;;) {
- c = *str++;
- if (c == 0 || q >= buf + buf_size - 1)
- break;
- *q++ = c;
- }
- *q = '\0';
-}
-
-/* strcat and truncate. */
-char *pstrcat(char *buf, int buf_size, const char *s)
-{
- int len;
- len = strlen(buf);
- if (len < buf_size)
- pstrcpy(buf + len, buf_size - len, s);
- return buf;
-}
-
-int strstart(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- p = str;
- q = val;
- while (*q != '\0') {
- if (*p != *q)
- return 0;
- p++;
- q++;
- }
- if (ptr)
- *ptr = p;
- return 1;
-}
-
void cpu_outb(CPUState *env, int addr, int val)
{
#ifdef DEBUG_IOPORT
/***********************************************************/
/* character device */
+static void qemu_chr_event(CharDriverState *s, int event)
+{
+ if (!s->chr_event)
+ return;
+ s->chr_event(s->handler_opaque, event);
+}
+
+static void qemu_chr_reset_bh(void *opaque)
+{
+ CharDriverState *s = opaque;
+ qemu_chr_event(s, CHR_EVENT_RESET);
+ qemu_bh_delete(s->bh);
+ s->bh = NULL;
+}
+
+void qemu_chr_reset(CharDriverState *s)
+{
+ if (s->bh == NULL) {
+ s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
+ qemu_bh_schedule(s->bh);
+ }
+}
+
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
{
return s->chr_write(s, buf, len);
return s->chr_ioctl(s, cmd, arg);
}
+int qemu_chr_can_read(CharDriverState *s)
+{
+ if (!s->chr_can_read)
+ return 0;
+ return s->chr_can_read(s->handler_opaque);
+}
+
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
+{
+ s->chr_read(s->handler_opaque, buf, len);
+}
+
+
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
{
char buf[4096];
s->chr_send_event(s, event);
}
-void qemu_chr_add_read_handler(CharDriverState *s,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
+void qemu_chr_add_handlers(CharDriverState *s,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ void *opaque)
{
- s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
+ s->chr_can_read = fd_can_read;
+ s->chr_read = fd_read;
+ s->chr_event = fd_event;
+ s->handler_opaque = opaque;
+ if (s->chr_update_read_handler)
+ s->chr_update_read_handler(s);
}
-void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
-{
- s->chr_event = chr_event;
-}
-
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
return len;
}
-static void null_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
-{
-}
-
static CharDriverState *qemu_chr_open_null(void)
{
CharDriverState *chr;
if (!chr)
return NULL;
chr->chr_write = null_chr_write;
- chr->chr_add_read_handler = null_chr_add_read_handler;
return chr;
}
typedef struct {
int fd_in, fd_out;
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *fd_opaque;
int max_size;
} FDCharDriver;
CharDriverState *chr = opaque;
FDCharDriver *s = chr->opaque;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
return s->max_size;
}
return;
}
if (size > 0) {
- s->fd_read(s->fd_opaque, buf, size);
+ qemu_chr_read(chr, buf, size);
}
}
-static void fd_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
+static void fd_chr_update_read_handler(CharDriverState *chr)
{
FDCharDriver *s = chr->opaque;
if (s->fd_in >= 0) {
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->fd_opaque = opaque;
if (nographic && s->fd_in == 0) {
} else {
qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
s->fd_out = fd_out;
chr->opaque = s;
chr->chr_write = fd_chr_write;
- chr->chr_add_read_handler = fd_chr_add_read_handler;
+ chr->chr_update_read_handler = fd_chr_update_read_handler;
+
+ qemu_chr_reset(chr);
+
return chr;
}
chr = stdio_clients[client_index];
s = chr->opaque;
- chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+ qemu_chr_event(chr, CHR_EVENT_BREAK);
}
break;
case 'c':
if (client_index < stdio_nb_clients) {
uint8_t buf[1];
CharDriverState *chr;
- FDCharDriver *s;
chr = stdio_clients[client_index];
- s = chr->opaque;
- if (s->fd_can_read(s->fd_opaque) > 0) {
+ if (qemu_chr_can_read(chr) > 0) {
buf[0] = ch;
- s->fd_read(s->fd_opaque, buf, 1);
+ qemu_chr_read(chr, buf, 1);
} else if (term_fifo_size == 0) {
term_fifo[term_fifo_size++] = ch;
}
static int stdio_read_poll(void *opaque)
{
CharDriverState *chr;
- FDCharDriver *s;
if (client_index < stdio_nb_clients) {
chr = stdio_clients[client_index];
- s = chr->opaque;
/* try to flush the queue if needed */
- if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) {
- s->fd_read(s->fd_opaque, term_fifo, 1);
+ if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
+ qemu_chr_read(chr, term_fifo, 1);
term_fifo_size = 0;
}
/* see if we can absorb more chars */
if (!chr)
return NULL;
chr->chr_ioctl = tty_serial_ioctl;
+ qemu_chr_reset(chr);
return chr;
}
}
chr->opaque = (void *)fd;
chr->chr_write = null_chr_write;
- chr->chr_add_read_handler = null_chr_add_read_handler;
chr->chr_ioctl = pp_ioctl;
+
+ qemu_chr_reset(chr);
+
return chr;
}
#ifdef _WIN32
typedef struct {
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *win_opaque;
int max_size;
HANDLE hcom, hrecv, hsend;
OVERLAPPED orecv, osend;
static int win_chr_poll(void *opaque);
static int win_chr_pipe_poll(void *opaque);
-static void win_chr_close2(WinCharState *s)
+static void win_chr_close(CharDriverState *chr)
{
+ WinCharState *s = chr->opaque;
+
if (s->hsend) {
CloseHandle(s->hsend);
s->hsend = NULL;
s->hcom = NULL;
}
if (s->fpipe)
- qemu_del_polling_cb(win_chr_pipe_poll, s);
+ qemu_del_polling_cb(win_chr_pipe_poll, chr);
else
- qemu_del_polling_cb(win_chr_poll, s);
+ qemu_del_polling_cb(win_chr_poll, chr);
}
-static void win_chr_close(CharDriverState *chr)
+static int win_chr_init(CharDriverState *chr, const char *filename)
{
WinCharState *s = chr->opaque;
- win_chr_close2(s);
-}
-
-static int win_chr_init(WinCharState *s, const char *filename)
-{
COMMCONFIG comcfg;
COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
COMSTAT comstat;
fprintf(stderr, "Failed ClearCommError\n");
goto fail;
}
- qemu_add_polling_cb(win_chr_poll, s);
+ qemu_add_polling_cb(win_chr_poll, chr);
return 0;
fail:
- win_chr_close2(s);
+ win_chr_close(chr);
return -1;
}
return len1 - len;
}
-static int win_chr_read_poll(WinCharState *s)
+static int win_chr_read_poll(CharDriverState *chr)
{
- s->max_size = s->fd_can_read(s->win_opaque);
+ WinCharState *s = chr->opaque;
+
+ s->max_size = qemu_chr_can_read(chr);
return s->max_size;
}
-
-static void win_chr_readfile(WinCharState *s)
+
+static void win_chr_readfile(CharDriverState *chr)
{
+ WinCharState *s = chr->opaque;
int ret, err;
uint8_t buf[1024];
DWORD size;
}
if (size > 0) {
- s->fd_read(s->win_opaque, buf, size);
+ qemu_chr_read(chr, buf, size);
}
}
-static void win_chr_read(WinCharState *s)
+static void win_chr_read(CharDriverState *chr)
{
+ WinCharState *s = chr->opaque;
+
if (s->len > s->max_size)
s->len = s->max_size;
if (s->len == 0)
return;
- win_chr_readfile(s);
+ win_chr_readfile(chr);
}
static int win_chr_poll(void *opaque)
{
- WinCharState *s = opaque;
+ CharDriverState *chr = opaque;
+ WinCharState *s = chr->opaque;
COMSTAT status;
DWORD comerr;
ClearCommError(s->hcom, &comerr, &status);
if (status.cbInQue > 0) {
s->len = status.cbInQue;
- win_chr_read_poll(s);
- win_chr_read(s);
+ win_chr_read_poll(chr);
+ win_chr_read(chr);
return 1;
}
return 0;
}
-static void win_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
-{
- WinCharState *s = chr->opaque;
-
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->win_opaque = opaque;
-}
-
static CharDriverState *qemu_chr_open_win(const char *filename)
{
CharDriverState *chr;
}
chr->opaque = s;
chr->chr_write = win_chr_write;
- chr->chr_add_read_handler = win_chr_add_read_handler;
chr->chr_close = win_chr_close;
- if (win_chr_init(s, filename) < 0) {
+ if (win_chr_init(chr, filename) < 0) {
free(s);
free(chr);
return NULL;
}
+ qemu_chr_reset(chr);
return chr;
}
static int win_chr_pipe_poll(void *opaque)
{
- WinCharState *s = opaque;
+ CharDriverState *chr = opaque;
+ WinCharState *s = chr->opaque;
DWORD size;
PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
if (size > 0) {
s->len = size;
- win_chr_read_poll(s);
- win_chr_read(s);
+ win_chr_read_poll(chr);
+ win_chr_read(chr);
return 1;
}
return 0;
}
-static int win_chr_pipe_init(WinCharState *s, const char *filename)
+static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
{
+ WinCharState *s = chr->opaque;
OVERLAPPED ov;
int ret;
DWORD size;
CloseHandle(ov.hEvent);
ov.hEvent = NULL;
}
- qemu_add_polling_cb(win_chr_pipe_poll, s);
+ qemu_add_polling_cb(win_chr_pipe_poll, chr);
return 0;
fail:
- win_chr_close2(s);
+ win_chr_close(chr);
return -1;
}
}
chr->opaque = s;
chr->chr_write = win_chr_write;
- chr->chr_add_read_handler = win_chr_add_read_handler;
chr->chr_close = win_chr_close;
- if (win_chr_pipe_init(s, filename) < 0) {
+ if (win_chr_pipe_init(chr, filename) < 0) {
free(s);
free(chr);
return NULL;
}
+ qemu_chr_reset(chr);
return chr;
}
s->hcom = fd_out;
chr->opaque = s;
chr->chr_write = win_chr_write;
- chr->chr_add_read_handler = win_chr_add_read_handler;
+ qemu_chr_reset(chr);
return chr;
}
/* UDP Net console */
typedef struct {
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *fd_opaque;
int fd;
struct sockaddr_in daddr;
char buf[1024];
CharDriverState *chr = opaque;
NetCharDriver *s = chr->opaque;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
/* If there were any stray characters in the queue process them
* first
*/
while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+ qemu_chr_read(chr, &s->buf[s->bufptr], 1);
s->bufptr++;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
}
return s->max_size;
}
s->bufptr = 0;
while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+ qemu_chr_read(chr, &s->buf[s->bufptr], 1);
s->bufptr++;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
}
}
-static void udp_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
+static void udp_chr_update_read_handler(CharDriverState *chr)
{
NetCharDriver *s = chr->opaque;
if (s->fd >= 0) {
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->fd_opaque = opaque;
qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
udp_chr_read, NULL, chr);
}
s->bufptr = 0;
chr->opaque = s;
chr->chr_write = udp_chr_write;
- chr->chr_add_read_handler = udp_chr_add_read_handler;
+ chr->chr_update_read_handler = udp_chr_update_read_handler;
return chr;
return_err:
/* TCP Net console */
typedef struct {
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
- void *fd_opaque;
int fd, listen_fd;
int connected;
int max_size;
int do_telnetopt;
+ int do_nodelay;
int is_unix;
} TCPCharDriver;
TCPCharDriver *s = chr->opaque;
if (!s->connected)
return 0;
- if (!s->fd_can_read)
- return 0;
- s->max_size = s->fd_can_read(s->fd_opaque);
+ s->max_size = qemu_chr_can_read(chr);
return s->max_size;
}
} else {
if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
/* Handle IAC break commands by sending a serial break */
- chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+ qemu_chr_event(chr, CHR_EVENT_BREAK);
s->do_telnetopt++;
}
s->do_telnetopt++;
if (s->do_telnetopt)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
if (size > 0)
- s->fd_read(s->fd_opaque, buf, size);
+ qemu_chr_read(chr, buf, size);
}
}
-static void tcp_chr_add_read_handler(CharDriverState *chr,
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque)
-{
- TCPCharDriver *s = chr->opaque;
-
- s->fd_can_read = fd_can_read;
- s->fd_read = fd_read;
- s->fd_opaque = opaque;
-}
-
static void tcp_chr_connect(void *opaque)
{
CharDriverState *chr = opaque;
s->connected = 1;
qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
tcp_chr_read, NULL, chr);
+ qemu_chr_reset(chr);
}
#define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
send(fd, (char *)buf, 3, 0);
}
+static void socket_set_nodelay(int fd)
+{
+ int val = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+}
+
static void tcp_chr_accept(void *opaque)
{
CharDriverState *chr = opaque;
}
}
socket_set_nonblock(fd);
+ if (s->do_nodelay)
+ socket_set_nodelay(fd);
s->fd = fd;
qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
tcp_chr_connect(chr);
int fd = -1, ret, err, val;
int is_listen = 0;
int is_waitconnect = 1;
+ int do_nodelay = 0;
const char *ptr;
struct sockaddr_in saddr;
#ifndef _WIN32
is_listen = 1;
} else if (!strncmp(ptr,"nowait",6)) {
is_waitconnect = 0;
+ } else if (!strncmp(ptr,"nodelay",6)) {
+ do_nodelay = 1;
} else {
printf("Unknown option: %s\n", ptr);
goto fail;
s->fd = -1;
s->listen_fd = -1;
s->is_unix = is_unix;
+ s->do_nodelay = do_nodelay && !is_unix;
chr->opaque = s;
chr->chr_write = tcp_chr_write;
- chr->chr_add_read_handler = tcp_chr_add_read_handler;
chr->chr_close = tcp_chr_close;
if (is_listen) {
}
}
s->fd = fd;
+ socket_set_nodelay(fd);
if (s->connected)
tcp_chr_connect(chr);
else
uint8_t buf[4096];
int size;
+#ifdef __sun__
+ struct strbuf sbuf;
+ int f = 0;
+ sbuf.maxlen = sizeof(buf);
+ sbuf.buf = buf;
+ size = getmsg(s->fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1;
+#else
size = read(s->fd, buf, sizeof(buf));
+#endif
if (size > 0) {
qemu_send_packet(s->vc, buf, size);
}
return fd;
}
#elif defined(__sun__)
+#define TUNNEWPPA (('T'<<16) | 0x0001)
+/*
+ * Allocate TAP device, returns opened fd.
+ * Stores dev name in the first arg(must be large enough).
+ */
+int tap_alloc(char *dev)
+{
+ int tap_fd, if_fd, ppa = -1;
+ static int ip_fd = 0;
+ char *ptr;
+
+ static int arp_fd = 0;
+ int ip_muxid, arp_muxid;
+ struct strioctl strioc_if, strioc_ppa;
+ int link_type = I_PLINK;;
+ struct lifreq ifr;
+ char actual_name[32] = "";
+
+ memset(&ifr, 0x0, sizeof(ifr));
+
+ if( *dev ){
+ ptr = dev;
+ while( *ptr && !isdigit((int)*ptr) ) ptr++;
+ ppa = atoi(ptr);
+ }
+
+ /* Check if IP device was opened */
+ if( ip_fd )
+ close(ip_fd);
+
+ if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
+ syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)");
+ return -1;
+ }
+
+ if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){
+ syslog(LOG_ERR, "Can't open /dev/tap");
+ return -1;
+ }
+
+ /* Assign a new PPA and get its unit number. */
+ strioc_ppa.ic_cmd = TUNNEWPPA;
+ strioc_ppa.ic_timout = 0;
+ strioc_ppa.ic_len = sizeof(ppa);
+ strioc_ppa.ic_dp = (char *)&ppa;
+ if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
+ syslog (LOG_ERR, "Can't assign new interface");
+
+ if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){
+ syslog(LOG_ERR, "Can't open /dev/tap (2)");
+ return -1;
+ }
+ if(ioctl(if_fd, I_PUSH, "ip") < 0){
+ syslog(LOG_ERR, "Can't push IP module");
+ return -1;
+ }
+
+ if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
+ syslog(LOG_ERR, "Can't get flags\n");
+
+ snprintf (actual_name, 32, "tap%d", ppa);
+ strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name));
+
+ ifr.lifr_ppa = ppa;
+ /* Assign ppa according to the unit number returned by tun device */
+
+ if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
+ syslog (LOG_ERR, "Can't set PPA %d", ppa);
+ if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
+ syslog (LOG_ERR, "Can't get flags\n");
+ /* Push arp module to if_fd */
+ if (ioctl (if_fd, I_PUSH, "arp") < 0)
+ syslog (LOG_ERR, "Can't push ARP module (2)");
+
+ /* Push arp module to ip_fd */
+ if (ioctl (ip_fd, I_POP, NULL) < 0)
+ syslog (LOG_ERR, "I_POP failed\n");
+ if (ioctl (ip_fd, I_PUSH, "arp") < 0)
+ syslog (LOG_ERR, "Can't push ARP module (3)\n");
+ /* Open arp_fd */
+ if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0)
+ syslog (LOG_ERR, "Can't open %s\n", "/dev/tap");
+
+ /* Set ifname to arp */
+ strioc_if.ic_cmd = SIOCSLIFNAME;
+ strioc_if.ic_timout = 0;
+ strioc_if.ic_len = sizeof(ifr);
+ strioc_if.ic_dp = (char *)𝔦
+ if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
+ syslog (LOG_ERR, "Can't set ifname to arp\n");
+ }
+
+ if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
+ syslog(LOG_ERR, "Can't link TAP device to IP");
+ return -1;
+ }
+
+ if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
+ syslog (LOG_ERR, "Can't link TAP device to ARP");
+
+ close (if_fd);
+
+ memset(&ifr, 0x0, sizeof(ifr));
+ strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name));
+ ifr.lifr_ip_muxid = ip_muxid;
+ ifr.lifr_arp_muxid = arp_muxid;
+
+ if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0)
+ {
+ ioctl (ip_fd, I_PUNLINK , arp_muxid);
+ ioctl (ip_fd, I_PUNLINK, ip_muxid);
+ syslog (LOG_ERR, "Can't set multiplexor id");
+ }
+
+ sprintf(dev, "tap%d", ppa);
+ return tap_fd;
+}
+
static int tap_open(char *ifname, int ifname_size)
{
- fprintf(stderr, "warning: tap_open not yet implemented\n");
- return -1;
+ char dev[10]="";
+ int fd;
+ if( (fd = tap_alloc(dev)) < 0 ){
+ fprintf(stderr, "Cannot allocate TAP device\n");
+ return -1;
+ }
+ pstrcpy(ifname, ifname_size, dev);
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ return fd;
}
#else
static int tap_open(char *ifname, int ifname_size)
if (fd < 0)
return -1;
- if (!setup_script)
+ if (!setup_script || !strcmp(setup_script, "no"))
setup_script = "";
if (setup_script[0] != '\0') {
/* try to launch network init script */
if (net_tap_fd_init(vlan, fd))
ret = 0;
} else {
- get_param_value(ifname, sizeof(ifname), "ifname", p);
+ if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
+ ifname[0] = '\0';
+ }
if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
}
}
}
-/* Parse IDE and SCSI disk options */
-static int disk_options_init(int num_ide_disks,
- char ide_disk_options[][DISK_OPTIONS_SIZE],
- int snapshot,
- int num_scsi_disks,
- char scsi_disk_options[][DISK_OPTIONS_SIZE],
- int cdrom_index,
- int cyls,
- int heads,
- int secs,
- int translation)
-{
- char buf[256];
- char dev_name[64];
- int id, i, j;
- int cdrom_device;
- int ide_cdrom_created = 0;
- int scsi_index;
- scsi_host_adapters temp_adapter;
-
- /* Process any IDE disks/cdroms */
- for (i=0; i< num_ide_disks; i++) {
- for (j=0; j<MAX_DISKS; j++) {
- if (ide_disk_options[j][0] == '\0')
- continue;
-
- if (get_param_value(buf, sizeof(buf),"type",ide_disk_options[j])) {
- if (!strcmp(buf, "disk")) {
- cdrom_device = 0;
- } else if (!strcmp(buf, "cdrom")) {
- cdrom_device = 1;
- ide_cdrom_created = 1;
- } else {
- fprintf(stderr, "qemu: invalid IDE disk type= value: %s\n", buf);
- return -1;
- }
- } else {
- cdrom_device = 0;
- }
-
- if (cdrom_device) {
- snprintf(dev_name, sizeof(dev_name), "cdrom%c", i + '0');
- } else {
- snprintf(dev_name, sizeof(dev_name), "hd%c", i + 'a');
- }
-
- if (!(get_param_value(buf, sizeof(buf),"img",ide_disk_options[j]))) {
- fprintf(stderr, "qemu: missing IDE disk img= value.\n");
- return -1;
- }
-
- if (!(bs_table[i] = bdrv_new(dev_name))) {
- fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name);
- return -1;
- }
-
- if (cdrom_device) {
- bdrv_set_type_hint(bs_table[i], BDRV_TYPE_CDROM);
- }
-
- if (bdrv_open(bs_table[i], buf, snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
- fprintf(stderr, "qemu: could not open hard disk image: '%s'\n",
- buf);
- return -1;
- }
- if (i == 0 && cyls != 0) {
- bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
- bdrv_set_translation_hint(bs_table[i], translation);
- }
- ide_disk_options[j][0] = '\0';
-
- if (i == cdrom_index) {
- cdrom_index = -1;
- }
- break; /* finished with this IDE device*/
- }
- }
-
- if (cdrom_index >= 0 && (!ide_cdrom_created)) {
- bs_table[cdrom_index] = bdrv_new("cdrom");
- bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
- }
-
- for(i = 0; i < num_scsi_disks; i++) {
-
-#if !defined(TARGET_SPARC) || defined(TARGET_SPARC64)
- temp_adapter = SCSI_LSI_53C895A;
- scsi_hba_lsi++;
-#else
- temp_adapter = SCSI_ESP;
-#endif
-
- /*Check for sdx= parameter */
- if (get_param_value(buf, sizeof(buf), "sdx", scsi_disk_options[i])) {
- if (buf[0] >= 'a' && buf[0] <= 'g') {
- scsi_index = buf[0] - 'a';
- } else{
- fprintf(stderr, "qemu: sdx= option for SCSI must be one letter from a-g. %s \n",buf);
- exit(1);
- }
- } else {
- scsi_index = 0;
- }
-
- /* Check for SCSI id specified. */
- if (get_param_value(buf, sizeof(buf),"id",scsi_disk_options[i])) {
- id = strtol(buf, NULL, 0);
- if (id < 0 || id > 6) {
- fprintf(stderr, "qemu: SCSI id must be from 0-6: %d\n", id);
- return -1;
- }
- /* Check if id already used */
- for(j = 0; j < MAX_SCSI_DISKS; j++) {
- if (scsi_disks_info[j].device_type != SCSI_NONE &&
- j != i &&
- scsi_disks_info[j].adapter == temp_adapter &&
- scsi_disks_info[j].id == id ) {
- fprintf(stderr, "qemu: SCSI id already used: %u\n", id);
- return -1;
- }
- }
- } else {
- id = -1;
- }
- scsi_disks_info[i].adapter = temp_adapter;
- scsi_disks_info[i].id = id;
-
- if (get_param_value(buf, sizeof(buf),"type",scsi_disk_options[i])) {
- if (!strcmp(buf, "disk")) {
- cdrom_device = 0;
- } else if (!strcmp(buf, "cdrom")) {
- cdrom_device = 1;
- } else {
- fprintf(stderr, "qemu: invalid SCSI disk type= value: %s\n", buf);
- return -1;
- }
- } else {
- cdrom_device = 0;
- }
-
- if (cdrom_device) {
- snprintf(dev_name, sizeof(buf), "cdrom%c", scsi_index + '0');
- scsi_disks_info[scsi_index].device_type = SCSI_CDROM;
- } else {
- snprintf(dev_name, sizeof(buf), "sd%c", scsi_index + 'a');
- scsi_disks_info[scsi_index].device_type = SCSI_DISK;
- }
-
- if (!(bs_scsi_table[scsi_index] = bdrv_new(dev_name))) {
- fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name);
- return -1;
- }
-
- /* Get image filename from options and then try to open it */
- if (get_param_value(buf, sizeof(buf),"img",scsi_disk_options[i])) {
- if (bdrv_open(bs_scsi_table[scsi_index], buf, 0) < 0) {
- fprintf(stderr, "qemu: could not open SCSI disk image img='%s'\n",buf);
- return -1;
- }
- } else {
- fprintf(stderr, "qemu: SCSI disk image not specified for sd%c \n", i + 'a');
- return -1;
- }
- if (cdrom_device) {
- bdrv_set_type_hint(bs_scsi_table[scsi_index], BDRV_TYPE_CDROM);
- }
- }
-
- return 0;
-}
-
-
/***********************************************************/
/* USB devices */
void help(void)
{
- printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard\n"
+ printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
"usage: %s [options] [disk_image]\n"
"\n"
"'disk_image' is a raw hard image image for IDE hard disk 0\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"
- "-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
- "-disk ide,img=file[,hdx=a..dd][,type=disk|cdrom] \n"
- " defaults are: hdx=a,type=disk \n"
- "-disk scsi,img=file[,sdx=a..g][,type=disk|cdrom][,id=n] \n"
- " defaults are: sdx=a,type=disk,id='auto assign' \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
"-no-quit disable SDL window close capability\n"
"-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n"
" connect the host TAP network interface to VLAN 'n' and use\n"
" the network script 'file' (default=%s);\n"
+ " use 'script=no' to disable script execution;\n"
" use 'fd=h' to connect to an already opened TAP interface\n"
#endif
"-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n"
QEMU_OPTION_no_acpi,
QEMU_OPTION_no_reboot,
QEMU_OPTION_daemonize,
- QEMU_OPTION_disk,
QEMU_OPTION_option_rom,
+ QEMU_OPTION_semihosting
};
typedef struct QEMUOption {
const QEMUOption qemu_options[] = {
{ "h", 0, QEMU_OPTION_h },
+ { "help", 0, QEMU_OPTION_h },
{ "M", HAS_ARG, QEMU_OPTION_M },
{ "fda", HAS_ARG, QEMU_OPTION_fda },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
{ "smp", HAS_ARG, QEMU_OPTION_smp },
{ "vnc", HAS_ARG, QEMU_OPTION_vnc },
- { "disk", HAS_ARG, QEMU_OPTION_disk },
-
+
/* temporary options */
{ "usb", 0, QEMU_OPTION_usb },
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
{ "no-reboot", 0, QEMU_OPTION_no_reboot },
{ "daemonize", 0, QEMU_OPTION_daemonize },
{ "option-rom", HAS_ARG, QEMU_OPTION_option_rom },
+#if defined(TARGET_ARM)
+ { "semihosting", 0, QEMU_OPTION_semihosting },
+#endif
{ NULL },
};
qemu_register_machine(&prep_machine);
#elif defined(TARGET_MIPS)
qemu_register_machine(&mips_machine);
+ qemu_register_machine(&mips_malta_machine);
#elif defined(TARGET_SPARC)
#ifdef TARGET_SPARC64
qemu_register_machine(&sun4u_machine);
int i, cdrom_index;
int snapshot, linux_boot;
const char *initrd_filename;
- const char *fd_filename[MAX_FD];
- char scsi_options[MAX_SCSI_DISKS] [DISK_OPTIONS_SIZE];
- char ide_options[MAX_DISKS] [DISK_OPTIONS_SIZE];
- int num_ide_disks;
- int num_scsi_disks;
+ const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
const char *kernel_filename, *kernel_cmdline;
DisplayState *ds = &display_state;
int cyls, heads, secs, translation;
- int start_emulation = 1;
char net_clients[MAX_NET_CLIENTS][256];
int nb_net_clients;
int optind;
register_machines();
machine = first_machine;
initrd_filename = NULL;
- for(i = 0; i < MAX_SCSI_DISKS; i++) {
- scsi_disks_info[i].device_type = SCSI_NONE;
- bs_scsi_table[i] = NULL;
- }
-
- num_ide_disks = 0;
- num_scsi_disks = 0;
-
for(i = 0; i < MAX_FD; i++)
fd_filename[i] = NULL;
- for(i = 0; i < MAX_DISKS; i++) {
- ide_options[i][0] = '\0';
- }
+ for(i = 0; i < MAX_DISKS; i++)
+ hd_filename[i] = NULL;
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
vga_ram_size = VGA_RAM_SIZE;
- bios_size = BIOS_SIZE;
#ifdef CONFIG_GDBSTUB
use_gdbstub = 0;
gdbstub_port = DEFAULT_GDBSTUB_PORT;
break;
r = argv[optind];
if (r[0] != '-') {
-
- /* Build new disk IDE syntax string */
- pstrcpy(ide_options[0],
- 14,
- "hdx=a,img=");
- /*Add on image filename */
- pstrcpy(&(ide_options[0][13]),
- sizeof(ide_options[0])-13,
- argv[optind++]);
- num_ide_disks++;
+ hd_filename[0] = argv[optind++];
} else {
const QEMUOption *popt;
optind++;
+ /* Treat --foo the same as -foo. */
+ if (r[1] == '-')
+ r++;
popt = qemu_options;
for(;;) {
if (!popt->name) {
case QEMU_OPTION_hdd:
{
int hd_index;
- const char newIDE_DiskSyntax [][10] = {
- "hdx=a,img=", "hdx=b,img=", "hdx=c,img=", "hdx=d,img=" };
-
hd_index = popt->index - QEMU_OPTION_hda;
- if (num_ide_disks >= MAX_DISKS) {
- fprintf(stderr, "qemu: too many IDE disks defined.\n");
- exit(1);
- }
- /* Build new disk IDE syntax string */
- pstrcpy(ide_options[hd_index],
- 11,
- newIDE_DiskSyntax[hd_index]);
- /* Add on image filename */
- pstrcpy(&(ide_options[hd_index][10]),
- sizeof(ide_options[0])-10,
- optarg);
- num_ide_disks++;
- }
- break;
- case QEMU_OPTION_disk: /*Combined IDE and SCSI, for disk and CDROM */
- {
- const char *p_input_char;
- char *p_output_string;
- char device[64];
- int disk_index;
-
- p_input_char = optarg;
- p_output_string = device;
- while (*p_input_char != '\0' && *p_input_char != ',') {
- if ((p_output_string - device) < sizeof(device) - 1)
- *p_output_string++ = *p_input_char;
- p_input_char++;
- }
- *p_output_string = '\0';
- if (*p_input_char == ',')
- p_input_char++;
-
- if (!strcmp(device, "scsi")) {
- if (num_scsi_disks >= MAX_SCSI_DISKS) {
- fprintf(stderr, "qemu: too many SCSI disks defined.\n");
- exit(1);
- }
- pstrcpy(scsi_options[num_scsi_disks],
- sizeof(scsi_options[0]),
- p_input_char);
- num_scsi_disks++;
- } else if (!strcmp(device,"ide")) {
- if (num_ide_disks >= MAX_DISKS) {
- fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n");
- exit(1);
- }
- disk_index = 0; /* default is hda */
- if (get_param_value(device, sizeof(device),"hdx",p_input_char)) {
- if (device[0] >= 'a' && device[0] <= 'd') {
- disk_index = device[0] - 'a';
- } else {
- fprintf(stderr, "qemu: invalid IDE disk hdx= value: %s\n", device);
- return -1;
- }
- }
- else disk_index=0;
- pstrcpy(ide_options[disk_index],
- sizeof(ide_options[0]),
- p_input_char);
- num_ide_disks++;
- } else {
- fprintf(stderr, "qemu: -disk option must specify IDE or SCSI: %s \n",device);
- exit(1);
- }
+ hd_filename[hd_index] = optarg;
+ if (hd_index == cdrom_index)
+ cdrom_index = -1;
}
break;
case QEMU_OPTION_snapshot:
kernel_cmdline = optarg;
break;
case QEMU_OPTION_cdrom:
-#if !defined(TARGET_SPARC) || defined(TARGET_SPARC64)
- /* Assume boot cdrom is IDE */
- {
- char buf[22];
- if (num_ide_disks >= MAX_DISKS) {
- fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n");
- exit(1);
- }
- snprintf(buf, sizeof(buf), "type=cdrom,hdx=%c,img=", cdrom_index + 'a');
- /* Build new disk IDE syntax string */
- pstrcpy(ide_options[cdrom_index],
- 22,
- buf);
- /* Add on image filename */
- pstrcpy(&(ide_options[cdrom_index][21]),
- sizeof(ide_options[0])-21,
- optarg);
- num_ide_disks++;
- }
-#else
- /* Assume boot cdrom is SCSI */
- {
- char buf[27];
- if (num_scsi_disks >= MAX_SCSI_DISKS) {
- fprintf(stderr, "qemu: too many SCSI disks/cdroms defined.\n");
- exit(1);
- }
- snprintf(buf, sizeof(buf), "type=cdrom,sdx=%c,id=%d,img=",
- num_scsi_disks + 'a', num_scsi_disks + 2);
- /* Build new disk SCSI syntax string */
- pstrcpy(scsi_options[num_scsi_disks],
- 27,
- buf);
- /* Add on image filename */
- pstrcpy(&(scsi_options[num_scsi_disks][26]),
- sizeof(scsi_options[0])-26,
- optarg);
- num_scsi_disks++;
+ if (cdrom_index >= 0) {
+ hd_filename[cdrom_index] = optarg;
}
-#endif
break;
case QEMU_OPTION_boot:
boot_device = optarg[0];
if (boot_device != 'a' &&
-#ifdef TARGET_SPARC
+#if defined(TARGET_SPARC) || defined(TARGET_I386)
// Network boot
boot_device != 'n' &&
#endif
bios_dir = optarg;
break;
case QEMU_OPTION_S:
- start_emulation = 0;
+ autostart = 0;
break;
case QEMU_OPTION_k:
keyboard_layout = optarg;
option_rom[nb_option_roms] = optarg;
nb_option_roms++;
break;
+ case QEMU_OPTION_semihosting:
+ semihosting_enabled = 1;
+ break;
}
}
}
linux_boot = (kernel_filename != NULL);
if (!linux_boot &&
- num_ide_disks == 0 &&
- num_scsi_disks == 0 &&
+ hd_filename[0] == '\0' &&
+ (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
fd_filename[0] == '\0')
help();
+ /* boot to floppy or the default cd if no hard disk defined yet */
+ if (hd_filename[0] == '\0' && boot_device == 'c') {
+ if (fd_filename[0] != '\0')
+ boot_device = 'a';
+ else
+ boot_device = 'd';
+ }
+
setvbuf(stdout, NULL, _IOLBF, 0);
init_timers();
exit(1);
}
- /* init the memory */
- phys_ram_size = ram_size + vga_ram_size + bios_size;
-
- for (i = 0; i < nb_option_roms; i++) {
- int ret = get_image_size(option_rom[i]);
- if (ret == -1) {
- fprintf(stderr, "Could not load option rom '%s'\n", option_rom[i]);
+#ifdef TARGET_I386
+ if (boot_device == 'n') {
+ for (i = 0; i < nb_nics; i++) {
+ const char *model = nd_table[i].model;
+ char buf[1024];
+ if (model == NULL)
+ model = "ne2k_pci";
+ snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);
+ if (get_image_size(buf) > 0) {
+ option_rom[nb_option_roms] = strdup(buf);
+ nb_option_roms++;
+ break;
+ }
+ }
+ if (i == nb_nics) {
+ fprintf(stderr, "No valid PXE rom found for network device\n");
exit(1);
}
- phys_ram_size += ret;
+ boot_device = 'c'; /* to prevent confusion by the BIOS */
}
+#endif
+
+ /* init the memory */
+ phys_ram_size = ram_size + vga_ram_size + MAX_BIOS_SIZE;
phys_ram_base = qemu_vmalloc(phys_ram_size);
if (!phys_ram_base) {
exit(1);
}
+ /* we always create the cdrom drive, even if no disk is there */
bdrv_init();
-
- /* open the virtual block devices, disks or CDRoms */
- if (disk_options_init(num_ide_disks,ide_options,snapshot,
- num_scsi_disks,scsi_options,
- cdrom_index,
- cyls, heads, secs, translation)){
- exit(1);
+ if (cdrom_index >= 0) {
+ bs_table[cdrom_index] = bdrv_new("cdrom");
+ bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
}
- /* boot to floppy or default cd if no hard disk */
- if (num_ide_disks == 0 && boot_device == 'c') {
- if (fd_filename[0] != '\0')
- boot_device = 'a';
- else
- boot_device = 'd';
+ /* open the virtual block devices */
+ for(i = 0; i < MAX_DISKS; i++) {
+ if (hd_filename[i]) {
+ if (!bs_table[i]) {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "hd%c", i + 'a');
+ bs_table[i] = bdrv_new(buf);
+ }
+ if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
+ fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
+ hd_filename[i]);
+ exit(1);
+ }
+ if (i == 0 && cyls != 0) {
+ bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
+ bdrv_set_translation_hint(bs_table[i], translation);
+ }
+ }
}
/* we always create at least one floppy disk */
#ifdef CONFIG_GDBSTUB
if (use_gdbstub) {
- if (gdbserver_start(gdbstub_port) < 0) {
- fprintf(stderr, "Could not open gdbserver socket on port %d\n",
+ /* 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",
gdbstub_port);
exit(1);
- } else {
- printf("Waiting gdb connection on port %d\n", gdbstub_port);
}
} else
#endif
{
/* XXX: simplify init */
read_passwords();
- if (start_emulation) {
+ if (autostart) {
vm_start();
}
}