#include "qemu/sockets.h"
#include "hw/hw.h"
#include "hw/boards.h"
+#include "sysemu/accel.h"
#include "hw/usb.h"
-#include "hw/pcmcia.h"
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
#include "hw/bt.h"
ram_addr_t ram_size;
const char *mem_path = NULL;
int mem_prealloc = 0; /* force preallocation of physical target memory */
+bool enable_mlock = false;
int nb_nics;
NICInfo nd_table[MAX_NICS];
int autostart;
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
int boot_menu;
-static bool boot_strict;
+bool boot_strict;
uint8_t *boot_splash_filedata;
size_t boot_splash_filedata_size;
uint8_t qemu_extra_params_fw[2];
int icount_align_option;
-typedef struct FWBootEntry FWBootEntry;
-
-struct FWBootEntry {
- QTAILQ_ENTRY(FWBootEntry) link;
- int32_t bootindex;
- DeviceState *dev;
- char *suffix;
-};
-
-static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
- QTAILQ_HEAD_INITIALIZER(fw_boot_order);
int nb_numa_nodes;
int max_numa_nodeid;
NodeInfo numa_info[MAX_NODES];
+/* The bytes in qemu_uuid[] are in the order specified by RFC4122, _not_ in the
+ * little-endian "wire format" described in the SMBIOS 2.6 specification.
+ */
uint8_t qemu_uuid[16];
bool qemu_uuid_set;
-static QEMUBootSetHandler *boot_set_handler;
-static void *boot_set_opaque;
-
static NotifierList exit_notifiers =
NOTIFIER_LIST_INITIALIZER(exit_notifiers);
static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
-static bool tcg_allowed = true;
bool xen_allowed;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
-static int tcg_tb_size;
static int has_defaults = 1;
static int default_serial = 1;
.merge_lists = true,
.head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
.desc = {
- {
- .name = "type",
- .type = QEMU_OPT_STRING,
- .help = "emulated machine"
- }, {
- .name = "accel",
- .type = QEMU_OPT_STRING,
- .help = "accelerator list",
- }, {
- .name = "kernel_irqchip",
- .type = QEMU_OPT_BOOL,
- .help = "use KVM in-kernel irqchip",
- }, {
- .name = "kvm_shadow_mem",
- .type = QEMU_OPT_SIZE,
- .help = "KVM shadow MMU size",
- }, {
- .name = "kernel",
- .type = QEMU_OPT_STRING,
- .help = "Linux kernel image file",
- }, {
- .name = "initrd",
- .type = QEMU_OPT_STRING,
- .help = "Linux initial ramdisk file",
- }, {
- .name = "append",
- .type = QEMU_OPT_STRING,
- .help = "Linux kernel command line",
- }, {
- .name = "dtb",
- .type = QEMU_OPT_STRING,
- .help = "Linux kernel device tree file",
- }, {
- .name = "dumpdtb",
- .type = QEMU_OPT_STRING,
- .help = "Dump current dtb to a file and quit",
- }, {
- .name = "phandle_start",
- .type = QEMU_OPT_NUMBER,
- .help = "The first phandle ID we may generate dynamically",
- }, {
- .name = "dt_compatible",
- .type = QEMU_OPT_STRING,
- .help = "Overrides the \"compatible\" property of the dt root node",
- }, {
- .name = "dump-guest-core",
- .type = QEMU_OPT_BOOL,
- .help = "Include guest memory in a core dump",
- }, {
- .name = "mem-merge",
- .type = QEMU_OPT_BOOL,
- .help = "enable/disable memory merge support",
- },{
- .name = "usb",
- .type = QEMU_OPT_BOOL,
- .help = "Set on/off to enable/disable usb",
- },{
- .name = "firmware",
- .type = QEMU_OPT_STRING,
- .help = "firmware image",
- },{
- .name = "kvm-type",
- .type = QEMU_OPT_STRING,
- .help = "Specifies the KVM virtualization mode (HV, PR)",
- },{
- .name = PC_MACHINE_MAX_RAM_BELOW_4G,
- .type = QEMU_OPT_SIZE,
- .help = "maximum ram below the 4G boundary (32bit boundary)",
- },{
- .name = "iommu",
- .type = QEMU_OPT_BOOL,
- .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
- },
- { /* End of list */ }
+ /*
+ * no elements => accept any
+ * sanity checking will happen later
+ * when setting machine properties
+ */
+ { }
},
};
},
};
+static QemuOptsList qemu_semihosting_config_opts = {
+ .name = "semihosting-config",
+ .implied_opt_name = "enable",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
+ .desc = {
+ {
+ .name = "enable",
+ .type = QEMU_OPT_BOOL,
+ }, {
+ .name = "target",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
/**
* Get machine options
*
int index, const char *optstr)
{
QemuOpts *opts;
+ DriveInfo *dinfo;
if (!enable || drive_get_by_index(type, index)) {
return;
if (snapshot) {
drive_enable_snapshot(opts, NULL);
}
- if (!drive_new(opts, type)) {
- exit(1);
- }
-}
-
-void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
-{
- boot_set_handler = func;
- boot_set_opaque = opaque;
-}
-
-int qemu_boot_set(const char *boot_order)
-{
- if (!boot_set_handler) {
- return -EINVAL;
- }
- return boot_set_handler(boot_set_opaque, boot_order);
-}
-
-static void validate_bootdevices(const char *devices)
-{
- /* We just do some generic consistency checks */
- const char *p;
- int bitmap = 0;
-
- for (p = devices; *p != '\0'; p++) {
- /* Allowed boot devices are:
- * a-b: floppy disk drives
- * c-f: IDE disk drives
- * g-m: machine implementation dependent drives
- * n-p: network devices
- * It's up to each machine implementation to check if the given boot
- * devices match the actual hardware implementation and firmware
- * features.
- */
- if (*p < 'a' || *p > 'p') {
- fprintf(stderr, "Invalid boot device '%c'\n", *p);
- exit(1);
- }
- if (bitmap & (1 << (*p - 'a'))) {
- fprintf(stderr, "Boot device '%c' was given twice\n", *p);
- exit(1);
- }
- bitmap |= 1 << (*p - 'a');
- }
-}
-
-static void restore_boot_order(void *opaque)
-{
- char *normal_boot_order = opaque;
- static int first = 1;
-
- /* Restore boot order and remove ourselves after the first boot */
- if (first) {
- first = 0;
- return;
- }
-
- qemu_boot_set(normal_boot_order);
-
- qemu_unregister_reset(restore_boot_order, normal_boot_order);
- g_free(normal_boot_order);
-}
-
-void add_boot_device_path(int32_t bootindex, DeviceState *dev,
- const char *suffix)
-{
- FWBootEntry *node, *i;
-
- if (bootindex < 0) {
- return;
- }
-
- assert(dev != NULL || suffix != NULL);
-
- node = g_malloc0(sizeof(FWBootEntry));
- node->bootindex = bootindex;
- node->suffix = g_strdup(suffix);
- node->dev = dev;
-
- QTAILQ_FOREACH(i, &fw_boot_order, link) {
- if (i->bootindex == bootindex) {
- fprintf(stderr, "Two devices with same boot index %d\n", bootindex);
- exit(1);
- } else if (i->bootindex < bootindex) {
- continue;
- }
- QTAILQ_INSERT_BEFORE(i, node, link);
- return;
- }
- QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
-}
-
-DeviceState *get_boot_device(uint32_t position)
-{
- uint32_t counter = 0;
- FWBootEntry *i = NULL;
- DeviceState *res = NULL;
-
- if (!QTAILQ_EMPTY(&fw_boot_order)) {
- QTAILQ_FOREACH(i, &fw_boot_order, link) {
- if (counter == position) {
- res = i->dev;
- break;
- }
- counter++;
- }
- }
- return res;
-}
-
-/*
- * This function returns null terminated string that consist of new line
- * separated device paths.
- *
- * memory pointed by "size" is assigned total length of the array in bytes
- *
- */
-char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
-{
- FWBootEntry *i;
- size_t total = 0;
- char *list = NULL;
-
- QTAILQ_FOREACH(i, &fw_boot_order, link) {
- char *devpath = NULL, *bootpath;
- size_t len;
-
- if (i->dev) {
- devpath = qdev_get_fw_dev_path(i->dev);
- assert(devpath);
- }
- if (i->suffix && !ignore_suffixes && devpath) {
- size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
-
- bootpath = g_malloc(bootpathlen);
- snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
- g_free(devpath);
- } else if (devpath) {
- bootpath = devpath;
- } else if (!ignore_suffixes) {
- assert(i->suffix);
- bootpath = g_strdup(i->suffix);
- } else {
- bootpath = g_strdup("");
- }
-
- if (total) {
- list[total-1] = '\n';
- }
- len = strlen(bootpath) + 1;
- list = g_realloc(list, total + len);
- memcpy(&list[total], bootpath, len);
- total += len;
- g_free(bootpath);
+ dinfo = drive_new(opts, type);
+ if (!dinfo) {
+ exit(1);
}
+ dinfo->is_default = true;
- *size = total;
-
- if (boot_strict && *size > 0) {
- list[total-1] = '\n';
- list = g_realloc(list, total + 5);
- memcpy(&list[total], "HALT", 5);
- *size = total + 5;
- }
- return list;
}
static QemuOptsList qemu_smp_opts = {
}
-static void configure_realtime(QemuOpts *opts)
+static void realtime_init(void)
{
- bool enable_mlock;
-
- enable_mlock = qemu_opt_get_bool(opts, "mlock", true);
-
if (enable_mlock) {
if (os_mlock() < 0) {
fprintf(stderr, "qemu: locking memory failed\n");
}
}
-/***********************************************************/
-/* PCMCIA/Cardbus */
-
-static struct pcmcia_socket_entry_s {
- PCMCIASocket *socket;
- struct pcmcia_socket_entry_s *next;
-} *pcmcia_sockets = 0;
-
-void pcmcia_socket_register(PCMCIASocket *socket)
-{
- struct pcmcia_socket_entry_s *entry;
-
- entry = g_malloc(sizeof(struct pcmcia_socket_entry_s));
- entry->socket = socket;
- entry->next = pcmcia_sockets;
- pcmcia_sockets = entry;
-}
-
-void pcmcia_socket_unregister(PCMCIASocket *socket)
-{
- struct pcmcia_socket_entry_s *entry, **ptr;
-
- ptr = &pcmcia_sockets;
- for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr)
- if (entry->socket == socket) {
- *ptr = entry->next;
- g_free(entry);
- }
-}
-
-void pcmcia_info(Monitor *mon, const QDict *qdict)
-{
- struct pcmcia_socket_entry_s *iter;
-
- if (!pcmcia_sockets)
- monitor_printf(mon, "No PCMCIA sockets\n");
-
- for (iter = pcmcia_sockets; iter; iter = iter->next)
- monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
- iter->socket->attached ? iter->socket->card_string :
- "Empty");
-}
-
/***********************************************************/
/* machine registration */
MachineClass *mc = MACHINE_CLASS(oc);
QEMUMachine *qm = data;
+ mc->family = qm->family;
mc->name = qm->name;
mc->alias = qm->alias;
mc->desc = qm->desc;
mc->hot_add_cpu = qm->hot_add_cpu;
mc->kvm_type = qm->kvm_type;
mc->block_default_type = qm->block_default_type;
+ mc->units_per_default_bus = qm->units_per_default_bus;
mc->max_cpus = qm->max_cpus;
mc->no_serial = qm->no_serial;
mc->no_parallel = qm->no_parallel;
mc->no_floppy = qm->no_floppy;
mc->no_cdrom = qm->no_cdrom;
mc->no_sdcard = qm->no_sdcard;
+ mc->has_dynamic_sysbus = qm->has_dynamic_sysbus;
mc->is_default = qm->is_default;
mc->default_machine_opts = qm->default_machine_opts;
mc->default_boot_order = qm->default_boot_order;
+ mc->default_display = qm->default_display;
mc->compat_props = qm->compat_props;
mc->hw_version = qm->hw_version;
}
return mach_list;
}
+static int machine_help_func(QemuOpts *opts, MachineState *machine)
+{
+ ObjectProperty *prop;
+
+ if (!qemu_opt_has_help_opt(opts)) {
+ return 0;
+ }
+
+ QTAILQ_FOREACH(prop, &OBJECT(machine)->properties, node) {
+ if (!prop->set) {
+ continue;
+ }
+
+ error_printf("%s.%s=%s", MACHINE_GET_CLASS(machine)->name,
+ prop->name, prop->type);
+ if (prop->description) {
+ error_printf(" (%s)\n", prop->description);
+ } else {
+ error_printf("\n");
+ }
+ }
+
+ return 1;
+}
+
/***********************************************************/
/* main execution loop */
static int qemu_shutdown_requested(void)
{
- int r = shutdown_requested;
- shutdown_requested = 0;
- return r;
+ return atomic_xchg(&shutdown_requested, 0);
}
static void qemu_kill_report(void)
return 0;
}
-static void monitor_parse(const char *optarg, const char *mode)
+static void monitor_parse(const char *optarg, const char *mode, bool pretty)
{
static int monitor_device_index = 0;
QemuOpts *opts;
}
qemu_opt_set(opts, "mode", mode);
qemu_opt_set(opts, "chardev", label);
+ qemu_opt_set_bool(opts, "pretty", pretty);
if (def)
qemu_opt_set(opts, "default", "on");
monitor_device_index++;
return 0;
}
-static MachineClass *machine_parse(const char *name)
+static gint machine_class_cmp(gconstpointer a, gconstpointer b)
+{
+ const MachineClass *mc1 = a, *mc2 = b;
+ int res;
+
+ if (mc1->family == NULL) {
+ if (mc2->family == NULL) {
+ /* Compare standalone machine types against each other; they sort
+ * in increasing order.
+ */
+ return strcmp(object_class_get_name(OBJECT_CLASS(mc1)),
+ object_class_get_name(OBJECT_CLASS(mc2)));
+ }
+
+ /* Standalone machine types sort after families. */
+ return 1;
+ }
+
+ if (mc2->family == NULL) {
+ /* Families sort before standalone machine types. */
+ return -1;
+ }
+
+ /* Families sort between each other alphabetically increasingly. */
+ res = strcmp(mc1->family, mc2->family);
+ if (res != 0) {
+ return res;
+ }
+
+ /* Within the same family, machine types sort in decreasing order. */
+ return strcmp(object_class_get_name(OBJECT_CLASS(mc2)),
+ object_class_get_name(OBJECT_CLASS(mc1)));
+}
+
+ static MachineClass *machine_parse(const char *name)
{
MachineClass *mc = NULL;
GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
error_printf("Use -machine help to list supported machines!\n");
} else {
printf("Supported machines are:\n");
+ machines = g_slist_sort(machines, machine_class_cmp);
for (el = machines; el; el = el->next) {
MachineClass *mc = el->data;
if (mc->alias) {
exit(!name || !is_help_option(name));
}
-static int tcg_init(MachineClass *mc)
-{
- tcg_exec_init(tcg_tb_size * 1024 * 1024);
- return 0;
-}
-
-static struct {
- const char *opt_name;
- const char *name;
- int (*available)(void);
- int (*init)(MachineClass *mc);
- bool *allowed;
-} accel_list[] = {
- { "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
- { "xen", "Xen", xen_available, xen_init, &xen_allowed },
- { "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
- { "qtest", "QTest", qtest_available, qtest_init_accel, &qtest_allowed },
-};
-
-static int configure_accelerator(MachineClass *mc)
-{
- const char *p;
- char buf[10];
- int i, ret;
- bool accel_initialised = false;
- bool init_failed = false;
-
- p = qemu_opt_get(qemu_get_machine_opts(), "accel");
- if (p == NULL) {
- /* Use the default "accelerator", tcg */
- p = "tcg";
- }
-
- while (!accel_initialised && *p != '\0') {
- if (*p == ':') {
- p++;
- }
- p = get_opt_name(buf, sizeof (buf), p, ':');
- for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
- if (strcmp(accel_list[i].opt_name, buf) == 0) {
- if (!accel_list[i].available()) {
- printf("%s not supported for this target\n",
- accel_list[i].name);
- break;
- }
- *(accel_list[i].allowed) = true;
- ret = accel_list[i].init(mc);
- if (ret < 0) {
- init_failed = true;
- fprintf(stderr, "failed to initialize %s: %s\n",
- accel_list[i].name,
- strerror(-ret));
- *(accel_list[i].allowed) = false;
- } else {
- accel_initialised = true;
- }
- break;
- }
- }
- if (i == ARRAY_SIZE(accel_list)) {
- fprintf(stderr, "\"%s\" accelerator does not exist.\n", buf);
- }
- }
-
- if (!accel_initialised) {
- if (!init_failed) {
- fprintf(stderr, "No accelerator found!\n");
- }
- exit(1);
- }
-
- if (init_failed) {
- fprintf(stderr, "Back to %s accelerator.\n", accel_list[i].name);
- }
-
- return !accel_initialised;
-}
-
void qemu_add_exit_notifier(Notifier *notify)
{
notifier_list_add(&exit_notifiers, notify);
void *opaque)
{
Object *obj = OBJECT(opaque);
- StringInputVisitor *siv;
Error *local_err = NULL;
char *c, *qom_name;
}
}
- siv = string_input_visitor_new(value);
- object_property_set(obj, string_input_get_visitor(siv), qom_name, &local_err);
- string_input_visitor_cleanup(siv);
+ object_property_parse(obj, value, qom_name, &local_err);
g_free(qom_name);
if (local_err) {
qemu_add_opts(&qemu_name_opts);
qemu_add_opts(&qemu_numa_opts);
qemu_add_opts(&qemu_icount_opts);
+ qemu_add_opts(&qemu_semihosting_config_opts);
runstate_init();
case QEMU_OPTION_monitor:
default_monitor = 0;
if (strncmp(optarg, "none", 4)) {
- monitor_parse(optarg, "readline");
+ monitor_parse(optarg, "readline", false);
}
break;
case QEMU_OPTION_qmp:
- monitor_parse(optarg, "control");
+ monitor_parse(optarg, "control", false);
+ default_monitor = 0;
+ break;
+ case QEMU_OPTION_qmp_pretty:
+ monitor_parse(optarg, "control", true);
default_monitor = 0;
break;
case QEMU_OPTION_mon:
break;
case QEMU_OPTION_semihosting:
semihosting_enabled = 1;
+ semihosting_target = SEMIHOSTING_TARGET_AUTO;
+ break;
+ case QEMU_OPTION_semihosting_config:
+ semihosting_enabled = 1;
+ opts = qemu_opts_parse(qemu_find_opts("semihosting-config"),
+ optarg, 0);
+ if (opts != NULL) {
+ semihosting_enabled = qemu_opt_get_bool(opts, "enable",
+ true);
+ const char *target = qemu_opt_get(opts, "target");
+ if (target != NULL) {
+ if (strcmp("native", target) == 0) {
+ semihosting_target = SEMIHOSTING_TARGET_NATIVE;
+ } else if (strcmp("gdb", target) == 0) {
+ semihosting_target = SEMIHOSTING_TARGET_GDB;
+ } else if (strcmp("auto", target) == 0) {
+ semihosting_target = SEMIHOSTING_TARGET_AUTO;
+ } else {
+ fprintf(stderr, "Unsupported semihosting-config"
+ " %s\n",
+ optarg);
+ exit(1);
+ }
+ } else {
+ semihosting_target = SEMIHOSTING_TARGET_AUTO;
+ }
+ } else {
+ fprintf(stderr, "Unsupported semihosting-config %s\n",
+ optarg);
+ exit(1);
+ }
break;
case QEMU_OPTION_tdf:
fprintf(stderr, "Warning: user space PIT time drift fix "
if (!opts) {
exit(1);
}
- configure_realtime(opts);
+ enable_mlock = qemu_opt_get_bool(opts, "mlock", true);
break;
case QEMU_OPTION_msg:
opts = qemu_opts_parse(qemu_find_opts("msg"), optarg, 0);
configure_msg(opts);
break;
case QEMU_OPTION_dump_vmstate:
+ if (vmstate_dump_file) {
+ fprintf(stderr, "qemu: only one '-dump-vmstate' "
+ "option may be given\n");
+ exit(1);
+ }
vmstate_dump_file = fopen(optarg, "w");
if (vmstate_dump_file == NULL) {
fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
current_machine = MACHINE(object_new(object_class_get_name(
OBJECT_CLASS(machine_class))));
+ if (machine_help_func(qemu_get_machine_opts(), current_machine)) {
+ exit(0);
+ }
object_property_add_child(object_get_root(), "machine",
OBJECT(current_machine), &error_abort);
cpu_exec_init_all();
add_device_config(DEV_SCLP, "stdio");
}
if (default_monitor)
- monitor_parse("stdio", "readline");
+ monitor_parse("stdio", "readline", false);
}
} else {
if (default_serial)
if (default_parallel)
add_device_config(DEV_PARALLEL, "vc:80Cx24C");
if (default_monitor)
- monitor_parse("vc:80Cx24C", "readline");
+ monitor_parse("vc:80Cx24C", "readline", false);
if (default_virtcon)
add_device_config(DEV_VIRTCON, "vc:80Cx24C");
if (default_sclp) {
#endif
if (pid_file && qemu_create_pidfile(pid_file) != 0) {
- os_pidfile_error();
+ fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
exit(1);
}
exit(1);
}
- configure_accelerator(machine_class);
+ configure_accelerator(current_machine);
if (qtest_chrdev) {
Error *local_err = NULL;
if (opts) {
char *normal_boot_order;
const char *order, *once;
+ Error *local_err = NULL;
order = qemu_opt_get(opts, "order");
if (order) {
- validate_bootdevices(order);
+ validate_bootdevices(order, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ exit(1);
+ }
boot_order = order;
}
once = qemu_opt_get(opts, "once");
if (once) {
- validate_bootdevices(once);
+ validate_bootdevices(once, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ exit(1);
+ }
normal_boot_order = g_strdup(boot_order);
boot_order = once;
qemu_register_reset(restore_boot_order, normal_boot_order);
blk_mig_init();
ram_mig_init();
+ /* If the currently selected machine wishes to override the units-per-bus
+ * property of its default HBA interface type, do so now. */
+ if (machine_class->units_per_default_bus) {
+ override_max_devs(machine_class->block_default_type,
+ machine_class->units_per_default_bus);
+ }
+
/* open the virtual block devices */
if (snapshot)
qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
/* If no default VGA is requested, the default is "none". */
if (default_vga) {
- if (cirrus_vga_available()) {
+ if (machine_class->default_display) {
+ vga_model = machine_class->default_display;
+ } else if (cirrus_vga_available()) {
vga_model = "cirrus";
} else if (vga_available()) {
vga_model = "std";
machine_class->init(current_machine);
+ realtime_init();
+
audio_init();
cpu_synchronize_all_post_init();
if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 1) != 0)
exit(1);
+ /* Did we create any drives that we failed to create a device for? */
+ drive_check_orphaned();
+
net_check_clients();
ds = init_displaystate();