diff --git a/devicemodel/Makefile b/devicemodel/Makefile index 6d1826c20..006694496 100644 --- a/devicemodel/Makefile +++ b/devicemodel/Makefile @@ -92,6 +92,7 @@ SRCS += hw/platform/ioapic.c SRCS += hw/platform/cmos_io.c SRCS += hw/platform/ioc.c SRCS += hw/platform/ioc_cbc.c +SRCS += hw/platform/pty_vuart.c SRCS += hw/platform/acpi/acpi.c SRCS += hw/platform/acpi/acpi_pm.c SRCS += hw/platform/rpmb/rpmb_sim.c diff --git a/devicemodel/hw/platform/ioc.c b/devicemodel/hw/platform/ioc.c index 7e01a5380..7055016e3 100644 --- a/devicemodel/hw/platform/ioc.c +++ b/devicemodel/hw/platform/ioc.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -64,6 +63,8 @@ #include #include +#include "pty_vuart.h" + #include "dm.h" #include "ioc.h" #include "vmmapi.h" @@ -709,83 +710,6 @@ ioc_open_native_ch(const char *dev_name) return fd; } -/* - * Check and create the directory. - * To avoid symlink failure if the directory does not exist. - */ -static int -check_dir(const char *file) -{ - char *tmp, *dir; - - tmp = strdup(file); - if (!tmp) { - DPRINTF("ioc falied to dup file, error:%s\r\n", - strerror(errno)); - return -1; - } - - dir = dirname(tmp); - if (access(dir, F_OK) && mkdir(dir, 0666)) { - DPRINTF("ioc falied to create dir:%s, erorr:%s\r\n", dir, - strerror(errno)); - free(tmp); - return -1; - } - free(tmp); - return 0; -} - -/* - * Open PTY master device for IOC mediator and the PTY slave device for virtual - * UART. The pair(master/slave) can work as a communication channel between - * IOC mediator and virtual UART. - */ -static int -ioc_open_virtual_uart(const char *dev_name) -{ - int fd; - char *slave_name; - struct termios attr; - - fd = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_NONBLOCK); - if (fd < 0) - goto open_err; - if (grantpt(fd) < 0) - goto pty_err; - if (unlockpt(fd) < 0) - goto pty_err; - slave_name = ptsname(fd); - if (!slave_name) - goto pty_err; - if ((unlink(dev_name) < 0) && errno != ENOENT) - goto pty_err; - /* - * The check_dir restriction is that only create one directory - * not support multi-level directroy. - */ - if (check_dir(dev_name) < 0) - goto pty_err; - if (symlink(slave_name, dev_name) < 0) - goto pty_err; - if (chmod(dev_name, 0660) < 0) - goto attr_err; - if (tcgetattr(fd, &attr) < 0) - goto attr_err; - cfmakeraw(&attr); - attr.c_cflag |= CLOCAL; - if (tcsetattr(fd, TCSANOW, &attr) < 0) - goto attr_err; - return fd; - -attr_err: - unlink(dev_name); -pty_err: - close(fd); -open_err: - return -1; -} - /* * Open native CBC cdevs and virtual UART. */ @@ -807,7 +731,7 @@ ioc_ch_init(struct ioc_dev *ioc) fd = ioc_open_native_ch(chl->name); break; case IOC_VIRTUAL_UART: - fd = ioc_open_virtual_uart(virtual_uart_path); + fd = pty_open_virtual_uart(virtual_uart_path); break; case IOC_LOCAL_EVENT: if (!pipe(pipe_fds)) { @@ -823,7 +747,7 @@ ioc_ch_init(struct ioc_dev *ioc) */ case IOC_NATIVE_DUMMY0: if (ioc_debug_enable) { - fd = ioc_open_virtual_uart(chl->name); + fd = pty_open_virtual_uart(chl->name); dummy0_sfd = open(chl->name, O_RDWR | O_NOCTTY | O_NONBLOCK); } else @@ -831,7 +755,7 @@ ioc_ch_init(struct ioc_dev *ioc) break; case IOC_NATIVE_DUMMY1: if (ioc_debug_enable) { - fd = ioc_open_virtual_uart(chl->name); + fd = pty_open_virtual_uart(chl->name); dummy1_sfd = open(chl->name, O_RDWR | O_NOCTTY | O_NONBLOCK); } else @@ -839,7 +763,7 @@ ioc_ch_init(struct ioc_dev *ioc) break; case IOC_NATIVE_DUMMY2: if (ioc_debug_enable) { - fd = ioc_open_virtual_uart(chl->name); + fd = pty_open_virtual_uart(chl->name); dummy2_sfd = open(chl->name, O_RDWR | O_NOCTTY | O_NONBLOCK); } else diff --git a/devicemodel/hw/platform/pty_vuart.c b/devicemodel/hw/platform/pty_vuart.c new file mode 100644 index 000000000..44dd63061 --- /dev/null +++ b/devicemodel/hw/platform/pty_vuart.c @@ -0,0 +1,96 @@ +/* + * Project Acrn + * Acrn-dm-pty + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" + +/* + * Check and create the directory. + * To avoid symlink failure if the directory does not exist. + */ +static int check_dir(const char *file) +{ + char *tmp, *dir; + + tmp = strdup(file); + if (!tmp) { + pr_err("failed to dup file, error:%s\n", strerror(errno)); + return -1; + } + + dir = dirname(tmp); + if (access(dir, F_OK) && mkdir(dir, 0666)) { + pr_err("failed to create dir:%s, erorr:%s\n", dir, strerror(errno)); + free(tmp); + return -1; + } + free(tmp); + return 0; +} + +/* + * Open PTY master device to used by caller and the PTY slave device for virtual + * UART. The pair(master/slave) can work as a communication channel between + * the caller and virtual UART. + */ +int pty_open_virtual_uart(const char *dev_name) +{ + int fd; + char *slave_name; + struct termios attr; + + fd = open("/dev/ptmx", O_RDWR | O_NOCTTY | O_NONBLOCK); + if (fd < 0) + goto open_err; + if (grantpt(fd) < 0) + goto pty_err; + if (unlockpt(fd) < 0) + goto pty_err; + slave_name = ptsname(fd); + if (!slave_name) + goto pty_err; + if ((unlink(dev_name) < 0) && errno != ENOENT) + goto pty_err; + /* + * The check_dir restriction is that only create one directory + * not support multi-level directroy. + */ + if (check_dir(dev_name) < 0) + goto pty_err; + if (symlink(slave_name, dev_name) < 0) + goto pty_err; + if (chmod(dev_name, 0660) < 0) + goto attr_err; + if (tcgetattr(fd, &attr) < 0) + goto attr_err; + cfmakeraw(&attr); + attr.c_cflag |= CLOCAL; + if (tcsetattr(fd, TCSANOW, &attr) < 0) + goto attr_err; + return fd; + +attr_err: + unlink(dev_name); +pty_err: + close(fd); +open_err: + return -1; +} diff --git a/devicemodel/include/pty_vuart.h b/devicemodel/include/pty_vuart.h new file mode 100644 index 000000000..001b191ba --- /dev/null +++ b/devicemodel/include/pty_vuart.h @@ -0,0 +1,16 @@ +/* + * Project Acrn + * Acrn-dm-pty + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __PTY_H__ +#define __PTY_H__ + +int pty_open_virtual_uart(const char *dev_name); + +#endif