aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/arm/ranchu.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/hw/arm/ranchu.c b/hw/arm/ranchu.c
index 8f8478d5b0..e8f96c30d5 100644
--- a/hw/arm/ranchu.c
+++ b/hw/arm/ranchu.c
@@ -35,6 +35,17 @@
#include "exec/address-spaces.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
+#include "qemu/config-file.h"
+#include "sysemu/char.h"
+#include "monitor/monitor.h"
+#include "hw/misc/android_pipe.h"
+
+/* Maximum number of emulators that can run at once (affects how
+ * far through the TCP port space from 5554 we will scan to find
+ * a pair of ports we can listen on)
+ */
+#define MAX_ANDROID_EMULATORS 64
+#define ANDROID_CONSOLE_BASEPORT 5554
#define NUM_VIRTIO_TRANSPORTS 32
@@ -420,6 +431,73 @@ static void *ranchu_dtb(const struct arm_boot_info *binfo, int *fdt_size)
return board->fdt;
}
+static CharDriverState *try_to_create_console_chardev(int portno)
+{
+ /* Try to create the chardev for the Android console on the specified port.
+ * This is equivalent to the command line options
+ * -chardev socket,id=monitor,host=127.0.0.1,port=NNN,server,nowait,telnet
+
+ * -mon chardev=monitor,mode=android-console
+ * Return true on success, false on failure (presumably port-in-use).
+ */
+ Error *err = NULL;
+ CharDriverState *chr;
+ QemuOpts *opts;
+ const char *chardev_opts =
+ "socket,id=private-chardev-for-android-monitor,"
+ "host=127.0.0.1,server,nowait,telnet";
+
+ opts = qemu_opts_parse(qemu_find_opts("chardev"), chardev_opts, 1);
+ assert(opts);
+ qemu_opt_set_number(opts, "port", portno);
+ chr = qemu_chr_new_from_opts(opts, NULL, &err);
+ if (err) {
+ /* Assume this was port-in-use */
+ qemu_opts_del(opts);
+ error_free(err);
+ return NULL;
+ }
+
+ qemu_chr_fe_claim_no_fail(chr);
+ return chr;
+}
+
+static void initialize_console_and_adb(void)
+{
+ /* Initialize the console and ADB, which must listen on two
+ * consecutive TCP ports starting from 5555 and working up until
+ * we manage to open both connections.
+ */
+ int baseport = ANDROID_CONSOLE_BASEPORT;
+ int tries = MAX_ANDROID_EMULATORS;
+ CharDriverState *chr;
+
+ for (; tries > 0; tries--, baseport += 2) {
+ chr = try_to_create_console_chardev(baseport);
+ if (!chr) {
+ continue;
+ }
+
+ if (!adb_server_init(baseport + 1)) {
+ qemu_chr_delete(chr);
+ chr = NULL;
+ continue;
+ }
+
+ /* Confirmed we have both ports, now we can create the console itself.
+ * This is equivalent to
+ * "-mon chardev=private-chardev,mode=android-console"
+ */
+ monitor_init(chr, MONITOR_ANDROID_CONSOLE | MONITOR_USE_READLINE);
+
+ printf("console on port %d, ADB on port %d\n", baseport, baseport + 1);
+ return;
+ }
+ error_report("it seems too many emulator instances are running "
+ "on this machine. Aborting\n");
+ exit(1);
+}
+
static void ranchu_init(MachineState *machine)
{
qemu_irq pic[NUM_IRQS];
@@ -499,6 +577,11 @@ static void ranchu_init(MachineState *machine)
*/
create_virtio_devices(vbi, pic);
+ /* Initialize the Android console and adb connection
+ * (must be done after the pipe has been realized).
+ */
+ initialize_console_and_adb();
+
vbi->bootinfo.ram_size = machine->ram_size;
vbi->bootinfo.kernel_filename = machine->kernel_filename;
vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline;