+def map_bool(b):
+ return "on" if b else "off"
+
+
+
+#################################
+# IO Backend Definitions
+#
+
+class IOBackend:
+ def __init__(self, opt, id_prefix="io") -> None:
+ self._type = get_config(opt, "type", required=True)
+ self._logfile = get_config(opt, "logfile")
+ self._id = f"{id_prefix}.{get_uniq()}"
+
+ def get_options(self):
+ opts = []
+ if self._logfile:
+ opts.append(f"logfile={self._logfile}")
+ return opts
+
+ def to_cmdline(self):
+ return join_attrs([
+ self._type, f"id={self._id}", *self.get_options()
+ ])
+
+ def name(self):
+ return self._id
+
+class FileIOBackend(IOBackend):
+ def __init__(self, opt) -> None:
+ super().__init__(opt)
+ self.__path = get_config(opt, "path", required=True)
+
+ def get_options(self):
+ opts = [
+ f"path={self.__path}"
+ ]
+ return opts + super().get_options()
+
+class SocketIOBackend(IOBackend):
+ def __init__(self, opt) -> None:
+ super().__init__(opt)
+ self.__protocol = self._type
+ self._type = "socket"
+ self.__host = get_config(opt, "host", default="localhost")
+ self.__port = get_config(opt, "port", required=True)
+ self.__server = bool(get_config(opt, "server", True))
+ self.__wait = bool(get_config(opt, "wait", True))
+
+ def get_options(self):
+ opts = [
+ f"host={self.__host}",
+ f"port={self.__port}",
+ f"server={map_bool(self.__server)}",
+ f"wait={map_bool(self.__wait)}",
+ ]
+ if self.__protocol == "telnet":
+ opts.append("telnet=on")
+ if self.__protocol == "ws":
+ opts.append("websocket=on")
+ return opts + super().get_options()
+
+def select_backend(opt):
+ bopt = get_config(opt, "io", required=True)
+ backend_type = get_config(bopt, "type", required=True)
+
+ if backend_type in ["telnet", "ws", "tcp"]:
+ return SocketIOBackend(bopt)
+
+ if backend_type in ["file", "pipe", "serial", "parallel"]:
+ return FileIOBackend(bopt)
+
+ return IOBackend(bopt)
+
+
+
+#################################
+# QEMU Emulated Device Definitions
+#