| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <signal.h>
- #include <string.h>
- #include <getopt.h>
- #include <poll.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/mount.h>
- #include <sys/param.h>
- #include <sys/reboot.h>
- #include "lib/bluetooth.h"
- #include "lib/hci.h"
- #include "lib/hci_lib.h"
- #include "tools/hciattach.h"
- #ifndef WAIT_ANY
- #define WAIT_ANY (-1)
- #endif
- #define CMDLINE_MAX (2048 * 10)
- static const char *own_binary;
- static char **test_argv;
- static int test_argc;
- static bool run_auto = false;
- static bool start_dbus = false;
- static bool start_monitor = false;
- static int num_devs = 0;
- static const char *qemu_binary = NULL;
- static const char *kernel_image = NULL;
- static const char *qemu_table[] = {
- "qemu-system-x86_64",
- "qemu-system-i386",
- "/usr/bin/qemu-system-x86_64",
- "/usr/bin/qemu-system-i386",
- NULL
- };
- static const char *find_qemu(void)
- {
- int i;
- for (i = 0; qemu_table[i]; i++) {
- struct stat st;
- if (!stat(qemu_table[i], &st))
- return qemu_table[i];
- }
- return NULL;
- }
- static const char *kernel_table[] = {
- "bzImage",
- "arch/x86/boot/bzImage",
- "vmlinux",
- "arch/x86/boot/vmlinux",
- NULL
- };
- static const char *find_kernel(void)
- {
- int i;
- for (i = 0; kernel_table[i]; i++) {
- struct stat st;
- if (!stat(kernel_table[i], &st))
- return kernel_table[i];
- }
- return NULL;
- }
- static const struct {
- const char *target;
- const char *linkpath;
- } dev_table[] = {
- { "/proc/self/fd", "/dev/fd" },
- { "/proc/self/fd/0", "/dev/stdin" },
- { "/proc/self/fd/1", "/dev/stdout" },
- { "/proc/self/fd/2", "/dev/stderr" },
- { }
- };
- static const struct {
- const char *fstype;
- const char *target;
- const char *options;
- unsigned long flags;
- } mount_table[] = {
- { "sysfs", "/sys", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
- { "proc", "/proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
- { "devtmpfs", "/dev", "mode=0755", MS_NOSUID|MS_STRICTATIME },
- { "devpts", "/dev/pts", "mode=0620", MS_NOSUID|MS_NOEXEC },
- { "tmpfs", "/dev/shm", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME },
- { "tmpfs", "/run", "mode=0755", MS_NOSUID|MS_NODEV|MS_STRICTATIME },
- { "tmpfs", "/tmp", NULL, 0 },
- { "debugfs", "/sys/kernel/debug", NULL, 0 },
- { }
- };
- static const char *config_table[] = {
- "/var/lib/bluetooth",
- "/etc/bluetooth",
- "/etc/dbus-1",
- "/usr/share/dbus-1",
- NULL
- };
- static void prepare_sandbox(void)
- {
- int i;
- for (i = 0; mount_table[i].fstype; i++) {
- struct stat st;
- if (lstat(mount_table[i].target, &st) < 0) {
- printf("Creating %s\n", mount_table[i].target);
- mkdir(mount_table[i].target, 0755);
- }
- printf("Mounting %s to %s\n", mount_table[i].fstype,
- mount_table[i].target);
- if (mount(mount_table[i].fstype,
- mount_table[i].target,
- mount_table[i].fstype,
- mount_table[i].flags,
- mount_table[i].options) < 0)
- perror("Failed to mount filesystem");
- }
- for (i = 0; dev_table[i].target; i++) {
- printf("Linking %s to %s\n", dev_table[i].linkpath,
- dev_table[i].target);
- if (symlink(dev_table[i].target, dev_table[i].linkpath) < 0)
- perror("Failed to create device symlink");
- }
- printf("Creating new session group leader\n");
- setsid();
- printf("Setting controlling terminal\n");
- ioctl(STDIN_FILENO, TIOCSCTTY, 1);
- for (i = 0; config_table[i]; i++) {
- printf("Creating %s\n", config_table[i]);
- if (mount("tmpfs", config_table[i], "tmpfs",
- MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
- "mode=0755") < 0)
- perror("Failed to create filesystem");
- }
- }
- static char *const qemu_argv[] = {
- "",
- "-nodefaults",
- "-no-user-config",
- "-monitor", "none",
- "-display", "none",
- "-machine", "type=q35,accel=kvm:tcg",
- "-m", "192M",
- "-nographic",
- "-vga", "none",
- "-net", "none",
- "-no-acpi",
- "-no-hpet",
- "-no-reboot",
- "-fsdev", "local,id=fsdev-root,path=/,readonly,security_model=none,"
- "multidevs=remap",
- "-device", "virtio-9p-pci,fsdev=fsdev-root,mount_tag=/dev/root",
- "-chardev", "stdio,id=con,mux=on",
- "-serial", "chardev:con",
- NULL
- };
- static char *const qemu_envp[] = {
- "HOME=/",
- NULL
- };
- static void check_virtualization(void)
- {
- #if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__))
- uint32_t ecx;
- __asm__ __volatile__("cpuid" : "=c" (ecx) : "a" (1) : "memory");
- if (!!(ecx & (1 << 5)))
- printf("Found support for Virtual Machine eXtensions\n");
- #endif
- }
- static void start_qemu(void)
- {
- char cwd[PATH_MAX/2], initcmd[PATH_MAX], testargs[PATH_MAX];
- char cmdline[CMDLINE_MAX];
- char **argv;
- int i, pos;
- check_virtualization();
- if (!getcwd(cwd, sizeof(cwd)))
- strcat(cwd, "/");
- if (own_binary[0] == '/')
- snprintf(initcmd, sizeof(initcmd), "%s", own_binary);
- else
- snprintf(initcmd, sizeof(initcmd), "%s/%s", cwd, own_binary);
- pos = snprintf(testargs, sizeof(testargs), "%s", test_argv[0]);
- for (i = 1; i < test_argc; i++) {
- int len = sizeof(testargs) - pos;
- pos += snprintf(testargs + pos, len, " %s", test_argv[i]);
- }
- snprintf(cmdline, sizeof(cmdline),
- "console=ttyS0,115200n8 earlyprintk=serial "
- "rootfstype=9p "
- "rootflags=trans=virtio,version=9p2000.L "
- "acpi=off pci=noacpi noapic quiet ro init=%s "
- "bluetooth.enable_ecred=1"
- "TESTHOME=%s TESTDBUS=%u TESTMONITOR=%u "
- "TESTDEVS=%d TESTAUTO=%u TESTARGS=\'%s\'",
- initcmd, cwd, start_dbus, start_monitor,
- num_devs, run_auto, testargs);
- argv = alloca(sizeof(qemu_argv) +
- (sizeof(char *) * (4 + (num_devs * 4))));
- memcpy(argv, qemu_argv, sizeof(qemu_argv));
- pos = (sizeof(qemu_argv) / sizeof(char *)) - 1;
- argv[0] = (char *) qemu_binary;
- argv[pos++] = "-kernel";
- argv[pos++] = (char *) kernel_image;
- argv[pos++] = "-append";
- argv[pos++] = (char *) cmdline;
- for (i = 0; i < num_devs; i++) {
- const char *path = "/tmp/bt-server-bredr";
- char *chrdev, *serdev;
- chrdev = alloca(32 + strlen(path));
- sprintf(chrdev, "socket,path=%s,id=bt%d", path, i);
- serdev = alloca(32);
- sprintf(serdev, "pci-serial,chardev=bt%d", i);
- argv[pos++] = "-chardev";
- argv[pos++] = chrdev;
- argv[pos++] = "-device";
- argv[pos++] = serdev;
- }
- argv[pos] = NULL;
- execve(argv[0], argv, qemu_envp);
- }
- static int open_serial(const char *path)
- {
- struct termios ti;
- int fd, saved_ldisc, ldisc = N_HCI;
- fd = open(path, O_RDWR | O_NOCTTY);
- if (fd < 0) {
- perror("Failed to open serial port");
- return -1;
- }
- if (tcflush(fd, TCIOFLUSH) < 0) {
- perror("Failed to flush serial port");
- close(fd);
- return -1;
- }
- if (ioctl(fd, TIOCGETD, &saved_ldisc) < 0) {
- perror("Failed get serial line discipline");
- close(fd);
- return -1;
- }
- /* Switch TTY to raw mode */
- memset(&ti, 0, sizeof(ti));
- cfmakeraw(&ti);
- ti.c_cflag |= (B115200 | CLOCAL | CREAD);
- /* Set flow control */
- ti.c_cflag |= CRTSCTS;
- if (tcsetattr(fd, TCSANOW, &ti) < 0) {
- perror("Failed to set serial port settings");
- close(fd);
- return -1;
- }
- if (ioctl(fd, TIOCSETD, &ldisc) < 0) {
- perror("Failed set serial line discipline");
- close(fd);
- return -1;
- }
- printf("Switched line discipline from %d to %d\n", saved_ldisc, ldisc);
- return fd;
- }
- static int attach_proto(const char *path, unsigned int proto,
- unsigned int mandatory_flags,
- unsigned int optional_flags)
- {
- unsigned int flags = mandatory_flags | optional_flags;
- int fd, dev_id;
- fd = open_serial(path);
- if (fd < 0)
- return -1;
- if (ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
- if (errno == EINVAL) {
- if (ioctl(fd, HCIUARTSETFLAGS, mandatory_flags) < 0) {
- perror("Failed to set mandatory flags");
- close(fd);
- return -1;
- }
- } else {
- perror("Failed to set flags");
- close(fd);
- return -1;
- }
- }
- if (ioctl(fd, HCIUARTSETPROTO, proto) < 0) {
- perror("Failed to set protocol");
- close(fd);
- return -1;
- }
- dev_id = ioctl(fd, HCIUARTGETDEVICE);
- if (dev_id < 0) {
- perror("Failed to get device id");
- close(fd);
- return -1;
- }
- printf("Device index %d attached\n", dev_id);
- return fd;
- }
- static void create_dbus_system_conf(void)
- {
- FILE *fp;
- fp = fopen("/etc/dbus-1/system.conf", "we");
- if (!fp)
- return;
- fputs("<!DOCTYPE busconfig PUBLIC "
- "\"-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN\" "
- "\"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd\">\n", fp);
- fputs("<busconfig>\n", fp);
- fputs("<type>system</type>\n", fp);
- fputs("<listen>unix:path=/run/dbus/system_bus_socket</listen>\n", fp);
- fputs("<policy context=\"default\">\n", fp);
- fputs("<allow user=\"*\"/>\n", fp);
- fputs("<allow own=\"*\"/>\n", fp);
- fputs("<allow send_type=\"method_call\"/>\n",fp);
- fputs("<allow send_type=\"signal\"/>\n", fp);
- fputs("<allow send_type=\"method_return\"/>\n", fp);
- fputs("<allow send_type=\"error\"/>\n", fp);
- fputs("<allow receive_type=\"method_call\"/>\n",fp);
- fputs("<allow receive_type=\"signal\"/>\n", fp);
- fputs("<allow receive_type=\"method_return\"/>\n", fp);
- fputs("<allow receive_type=\"error\"/>\n", fp);
- fputs("</policy>\n", fp);
- fputs("</busconfig>\n", fp);
- fclose(fp);
- if (symlink("/etc/dbus-1/system.conf",
- "/usr/share/dbus-1/system.conf") < 0)
- perror("Failed to create system.conf symlink");
- mkdir("/run/dbus", 0755);
- }
- static pid_t start_dbus_daemon(void)
- {
- char *argv[3], *envp[1];
- pid_t pid;
- int i;
- argv[0] = "/usr/bin/dbus-daemon";
- argv[1] = "--system";
- argv[2] = NULL;
- envp[0] = NULL;
- printf("Starting D-Bus daemon\n");
- pid = fork();
- if (pid < 0) {
- perror("Failed to fork new process");
- return -1;
- }
- if (pid == 0) {
- execve(argv[0], argv, envp);
- exit(EXIT_SUCCESS);
- }
- printf("D-Bus daemon process %d created\n", pid);
- for (i = 0; i < 20; i++) {
- struct stat st;
- if (!stat("/run/dbus/system_bus_socket", &st)) {
- printf("Found D-Bus daemon socket\n");
- break;
- }
- usleep(25 * 1000);
- }
- return pid;
- }
- static const char *daemon_table[] = {
- "bluetoothd",
- "src/bluetoothd",
- "/usr/sbin/bluetoothd",
- "/usr/libexec/bluetooth/bluetoothd",
- NULL
- };
- static pid_t start_bluetooth_daemon(const char *home)
- {
- const char *daemon = NULL;
- char *argv[6], *envp[2];
- pid_t pid;
- struct stat st;
- int i;
- if (chdir(home + 5) < 0) {
- perror("Failed to change home directory for daemon");
- return -1;
- }
- for (i = 0; daemon_table[i]; i++) {
- if (!stat(daemon_table[i], &st)) {
- daemon = daemon_table[i];
- break;
- }
- }
- if (!daemon) {
- fprintf(stderr, "Failed to locate Bluetooth daemon binary\n");
- return -1;
- }
- printf("Using Bluetooth daemon %s\n", daemon);
- argv[0] = (char *) daemon;
- argv[1] = "--nodetach";
- argv[2] = "-d";
- argv[3] = NULL;
- if (!stat("src/main.conf", &st)) {
- argv[3] = "-f";
- argv[4] = "src/main.conf";
- argv[5] = NULL;
- }
- envp[0] = "DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket";
- envp[1] = NULL;
- printf("Starting Bluetooth daemon\n");
- pid = fork();
- if (pid < 0) {
- perror("Failed to fork new process");
- return -1;
- }
- if (pid == 0) {
- execve(argv[0], argv, envp);
- exit(EXIT_SUCCESS);
- }
- printf("Bluetooth daemon process %d created\n", pid);
- return pid;
- }
- static const char *test_table[] = {
- "mgmt-tester",
- "smp-tester",
- "l2cap-tester",
- "rfcomm-tester",
- "sco-tester",
- "bnep-tester",
- "check-selftest",
- "tools/mgmt-tester",
- "tools/smp-tester",
- "tools/l2cap-tester",
- "tools/rfcomm-tester",
- "tools/sco-tester",
- "tools/bnep-tester",
- "tools/check-selftest",
- NULL
- };
- static const char *monitor_table[] = {
- "btmon",
- "monitor/btmon",
- "/usr/sbin/btmon",
- NULL
- };
- static pid_t start_btmon(const char *home)
- {
- const char *monitor = NULL;
- char *argv[3], *envp[2];
- pid_t pid;
- int i;
- if (chdir(home + 5) < 0) {
- perror("Failed to change home directory for monitor");
- return -1;
- }
- for (i = 0; monitor_table[i]; i++) {
- struct stat st;
- if (!stat(monitor_table[i], &st)) {
- monitor = monitor_table[i];
- break;
- }
- }
- if (!monitor) {
- fprintf(stderr, "Failed to locate Monitor binary\n");
- return -1;
- }
- printf("Using Monitor %s\n", monitor);
- argv[0] = (char *) monitor;
- argv[1] = "-t";
- argv[2] = NULL;
- printf("Starting Monitor\n");
- pid = fork();
- if (pid < 0) {
- perror("Failed to fork new process");
- return -1;
- }
- if (pid == 0) {
- execve(argv[0], argv, envp);
- exit(EXIT_SUCCESS);
- }
- printf("Monitor process %d created\n", pid);
- return pid;
- }
- static void run_command(char *cmdname, char *home)
- {
- char *argv[9], *envp[3];
- int pos = 0, idx = 0;
- int serial_fd;
- pid_t pid, dbus_pid, daemon_pid, monitor_pid;
- if (num_devs) {
- const char *node = "/dev/ttyS1";
- unsigned int basic_flags, extra_flags;
- printf("Attaching BR/EDR controller to %s\n", node);
- basic_flags = (1 << HCI_UART_RESET_ON_INIT);
- extra_flags = (1 << HCI_UART_VND_DETECT);
- serial_fd = attach_proto(node, HCI_UART_H4, basic_flags,
- extra_flags);
- } else
- serial_fd = -1;
- if (start_dbus) {
- create_dbus_system_conf();
- dbus_pid = start_dbus_daemon();
- daemon_pid = start_bluetooth_daemon(home);
- } else {
- dbus_pid = -1;
- daemon_pid = -1;
- }
- if (start_monitor)
- monitor_pid = start_btmon(home);
- else
- monitor_pid = -1;
- start_next:
- if (run_auto) {
- if (chdir(home + 5) < 0) {
- perror("Failed to change home test directory");
- return;
- }
- while (1) {
- struct stat st;
- if (!test_table[idx])
- return;
- if (!stat(test_table[idx], &st))
- break;
- idx++;
- }
- argv[0] = (char *) test_table[idx];
- argv[1] = "-q";
- argv[2] = NULL;
- } else {
- while (1) {
- char *ptr;
- ptr = strchr(cmdname, ' ');
- if (!ptr) {
- argv[pos++] = cmdname;
- break;
- }
- *ptr = '\0';
- argv[pos++] = cmdname;
- if (pos > 8)
- break;
- cmdname = ptr + 1;
- }
- argv[pos] = NULL;
- }
- pos = 0;
- envp[pos++] = "TERM=linux";
- if (home)
- envp[pos++] = home;
- envp[pos] = NULL;
- printf("Running command %s\n", argv[0]);
- pid = fork();
- if (pid < 0) {
- perror("Failed to fork new process");
- return;
- }
- if (pid == 0) {
- if (home) {
- printf("Changing into directory %s\n", home + 5);
- if (chdir(home + 5) < 0)
- perror("Failed to change directory");
- }
- execve(argv[0], argv, envp);
- exit(EXIT_SUCCESS);
- }
- printf("New process %d created\n", pid);
- while (1) {
- pid_t corpse;
- int status;
- corpse = waitpid(WAIT_ANY, &status, 0);
- if (corpse < 0 || corpse == 0)
- continue;
- if (WIFEXITED(status))
- printf("Process %d exited with status %d\n",
- corpse, WEXITSTATUS(status));
- else if (WIFSIGNALED(status))
- printf("Process %d terminated with signal %d\n",
- corpse, WTERMSIG(status));
- else if (WIFSTOPPED(status))
- printf("Process %d stopped with signal %d\n",
- corpse, WSTOPSIG(status));
- else if (WIFCONTINUED(status))
- printf("Process %d continued\n", corpse);
- if (corpse == dbus_pid) {
- printf("D-Bus daemon terminated\n");
- dbus_pid = -1;
- }
- if (corpse == daemon_pid) {
- printf("Bluetooth daemon terminated\n");
- daemon_pid = -1;
- }
- if (corpse == monitor_pid) {
- printf("Bluetooth monitor terminated\n");
- monitor_pid = -1;
- }
- if (corpse == pid)
- break;
- }
- if (run_auto) {
- idx++;
- goto start_next;
- }
- if (daemon_pid > 0)
- kill(daemon_pid, SIGTERM);
- if (dbus_pid > 0)
- kill(dbus_pid, SIGTERM);
- if (monitor_pid > 0)
- kill(monitor_pid, SIGTERM);
- if (serial_fd >= 0) {
- close(serial_fd);
- serial_fd = -1;
- }
- }
- static void run_tests(void)
- {
- char cmdline[CMDLINE_MAX], *ptr, *cmds, *home = NULL;
- FILE *fp;
- fp = fopen("/proc/cmdline", "re");
- if (!fp) {
- fprintf(stderr, "Failed to open kernel command line\n");
- return;
- }
- ptr = fgets(cmdline, sizeof(cmdline), fp);
- fclose(fp);
- if (!ptr) {
- fprintf(stderr, "Failed to read kernel command line\n");
- return;
- }
- ptr = strstr(cmdline, "TESTARGS=");
- if (!ptr) {
- fprintf(stderr, "No test command section found\n");
- return;
- }
- cmds = ptr + 10;
- ptr = strchr(cmds, '\'');
- if (!ptr) {
- fprintf(stderr, "Malformed test command section\n");
- return;
- }
- *ptr = '\0';
- ptr = strstr(cmdline, "TESTAUTO=1");
- if (ptr) {
- printf("Automatic test execution requested\n");
- run_auto= true;
- }
- ptr = strstr(cmdline, "TESTDEVS=1");
- if (ptr) {
- printf("Attachment of devices requested\n");
- num_devs = 1;
- }
- ptr = strstr(cmdline, "TESTDBUS=1");
- if (ptr) {
- printf("D-Bus daemon requested\n");
- start_dbus = true;
- }
- ptr = strstr(cmdline, "TESTMONITOR=1");
- if (ptr) {
- printf("Monitor requested\n");
- start_monitor = true;
- }
- ptr = strstr(cmdline, "TESTHOME=");
- if (ptr) {
- home = ptr + 4;
- ptr = strpbrk(home + 9, " \r\n");
- if (ptr)
- *ptr = '\0';
- }
- run_command(cmds, home);
- }
- static void usage(void)
- {
- printf("test-runner - Automated test execution utility\n"
- "Usage:\n");
- printf("\ttest-runner [options] [--] <command> [args]\n");
- printf("Options:\n"
- "\t-a, --auto Find tests and run them\n"
- "\t-d, --dbus Start D-Bus daemon\n"
- "\t-m, --monitor Start btmon\n"
- "\t-u, --unix [path] Provide serial device\n"
- "\t-q, --qemu <path> QEMU binary\n"
- "\t-k, --kernel <image> Kernel image (bzImage)\n"
- "\t-h, --help Show help options\n");
- }
- static const struct option main_options[] = {
- { "all", no_argument, NULL, 'a' },
- { "auto", no_argument, NULL, 'a' },
- { "unix", no_argument, NULL, 'u' },
- { "dbus", no_argument, NULL, 'd' },
- { "monitor", no_argument, NULL, 'm' },
- { "qemu", required_argument, NULL, 'q' },
- { "kernel", required_argument, NULL, 'k' },
- { "version", no_argument, NULL, 'v' },
- { "help", no_argument, NULL, 'h' },
- { }
- };
- int main(int argc, char *argv[])
- {
- if (getpid() == 1 && getppid() == 0) {
- prepare_sandbox();
- run_tests();
- sync();
- reboot(RB_AUTOBOOT);
- return EXIT_SUCCESS;
- }
- for (;;) {
- int opt;
- opt = getopt_long(argc, argv, "audmq:k:vh", main_options, NULL);
- if (opt < 0)
- break;
- switch (opt) {
- case 'a':
- run_auto = true;
- break;
- case 'u':
- num_devs = 1;
- break;
- case 'd':
- start_dbus = true;
- break;
- case 'm':
- start_monitor = true;
- break;
- case 'q':
- qemu_binary = optarg;
- break;
- case 'k':
- kernel_image = optarg;
- break;
- case 'v':
- printf("%s\n", VERSION);
- return EXIT_SUCCESS;
- case 'h':
- usage();
- return EXIT_SUCCESS;
- default:
- return EXIT_FAILURE;
- }
- }
- if (run_auto) {
- if (argc - optind > 0) {
- fprintf(stderr, "Invalid command line parameters\n");
- return EXIT_FAILURE;
- }
- } else {
- if (argc - optind < 1) {
- fprintf(stderr, "Failed to specify test command\n");
- return EXIT_FAILURE;
- }
- }
- own_binary = argv[0];
- test_argv = argv + optind;
- test_argc = argc - optind;
- if (!qemu_binary) {
- qemu_binary = find_qemu();
- if (!qemu_binary) {
- fprintf(stderr, "No default QEMU binary found\n");
- return EXIT_FAILURE;
- }
- }
- if (!kernel_image) {
- kernel_image = find_kernel();
- if (!kernel_image) {
- fprintf(stderr, "No default kernel image found\n");
- return EXIT_FAILURE;
- }
- }
- printf("Using QEMU binary %s\n", qemu_binary);
- printf("Using kernel image %s\n", kernel_image);
- start_qemu();
- return EXIT_SUCCESS;
- }
|