1 /*
2 * Copyright (C)2021-2022 Intel Corporation.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdbool.h>
11 #include <string.h>
12 #include <termios.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/file.h>
17 #include "uart_channel.h"
18 #include "command.h"
19 #include "socket.h"
20 #include "command_handler.h"
21 #include "log.h"
22 #include "config.h"
23
24 #define NODE_SIZE 5
25 #define S5_SOCKET_DIR "/var/lib/life_mngr"
26 #define S5_SOCKET_FMT "%s/monitor.sock"
27 #define SERVICE_VM_NAME "service_vm"
28
29 struct uart_channel *channel; /* uart server instance */
30 struct socket_dev *sock_server; /* socket server instance */
31
32 FILE *log_fd;
33
monitor_cmd_dispatch(const char * cmd_name,int fd)34 static void monitor_cmd_dispatch(const char *cmd_name, int fd)
35 {
36 struct command *cmd;
37
38 cmd = find_command(cmd_name);
39 if (cmd != NULL)
40 dispatch_command_handlers(cmd, fd);
41 else
42 LOG_PRINTF("Command [%s] is not supported, fd=%d\n", cmd_name, fd);
43 }
44 /**
45 * @brief open uart channel according to device name
46 *
47 * @param uart_dev_name one or more device names
48 * @return int all uart channel devices are open or not
49 */
create_service_vm_uart_channel_dev(char * uart_dev_name)50 static int create_service_vm_uart_channel_dev(char *uart_dev_name)
51 {
52 int ret = 0;
53 struct channel_dev *c_dev;
54 char *dev_name;
55 char *saveptr;
56
57 saveptr = uart_dev_name;
58 do {
59 dev_name = strtok_r(saveptr, ",", &saveptr);
60 c_dev = create_uart_channel_dev(channel, dev_name, monitor_cmd_dispatch);
61 if (c_dev == NULL) {
62 LOG_PRINTF("Failed to create uart channel device for %s\n", dev_name);
63 ret = -1;
64 break;
65 }
66 pthread_create(&c_dev->listen_thread, NULL, listen_uart_channel_dev, c_dev);
67 pthread_create(&c_dev->pool_thread, NULL, poll_and_dispatch_uart_channel_events, c_dev);
68 } while (strlen(saveptr) > 0U);
69
70 return ret;
71 }
72 /* TODO: will refine the name of init_socket_server_and_shutdown_commands */
init_socket_server_and_shutdown_commands(bool service_vm)73 int init_socket_server_and_shutdown_commands(bool service_vm)
74 {
75 int ret = 0;
76 char path[128] = S5_SOCKET_DIR;
77
78 ret = check_dir(path, CHK_CREAT);
79 if (ret < 0) {
80 LOG_PRINTF("%s %d\r\n", __func__, __LINE__);
81 return ret;
82 }
83 snprintf(path, sizeof(path), S5_SOCKET_FMT, S5_SOCKET_DIR);
84
85 sock_server = init_socket(path);
86 if (sock_server == NULL)
87 return -1;
88 ret = open_socket(sock_server, monitor_cmd_dispatch);
89 if (ret < 0)
90 return ret;
91 if (service_vm) {
92 register_command_handler(socket_req_shutdown_service_vm_handler,
93 sock_server, REQ_SYS_SHUTDOWN);
94 register_command_handler(socket_req_user_vm_shutdown_handler,
95 sock_server, USER_VM_SHUTDOWN);
96 register_command_handler(socket_req_user_vm_reboot_handler,
97 sock_server, USER_VM_REBOOT);
98 } else {
99 register_command_handler(socket_req_system_shutdown_user_vm_handler,
100 sock_server, REQ_SYS_SHUTDOWN);
101 register_command_handler(socket_req_system_reboot_user_vm_handler,
102 sock_server, REQ_SYS_REBOOT);
103 }
104 return ret;
105 }
106 /* TODO: will refine the name of init_uart_channel_devs_and_shutdown_commands */
init_uart_channel_devs_and_shutdown_commands(bool service_vm,char * uart_dev_name)107 int init_uart_channel_devs_and_shutdown_commands(bool service_vm, char *uart_dev_name)
108 {
109 int ret = 0;
110 struct channel_dev *c_dev;
111
112 channel = init_uart_channel(life_conf.vm_name);
113 if (channel == NULL)
114 return -1;
115 /**
116 * Open one or more uart channel for lifecycle manager in the service VM,
117 * open one uart channel for lifecycle manager in the user VM.
118 */
119 if (service_vm) {
120 register_command_handler(sync_cmd_handler, channel, SYNC_CMD);
121 register_command_handler(req_shutdown_handler, channel, REQ_SYS_SHUTDOWN);
122 register_command_handler(req_reboot_handler, channel, REQ_SYS_REBOOT);
123 register_command_handler(ack_poweroff_handler, channel, ACK_POWEROFF);
124 register_command_handler(ack_timeout_handler, channel, ACK_TIMEOUT);
125 register_command_handler(ack_user_vm_shutdown_cmd_handler, channel, ACK_USER_VM_SHUTDOWN);
126 register_command_handler(ack_user_vm_reboot_cmd_handler, channel, ACK_USER_VM_REBOOT);
127
128 ret = create_service_vm_uart_channel_dev(uart_dev_name);
129 if (ret < 0)
130 return ret;
131 } else {
132 register_command_handler(acked_sync_handler, channel, ACK_SYNC);
133 register_command_handler(poweroff_cmd_handler, channel, POWEROFF_CMD);
134 register_command_handler(user_vm_shutdown_cmd_handler, channel, USER_VM_SHUTDOWN);
135 register_command_handler(user_vm_reboot_cmd_handler, channel, USER_VM_REBOOT);
136 register_command_handler(acked_req_shutdown_reboot_handler, channel, ACK_REQ_SYS_SHUTDOWN);
137 register_command_handler(acked_req_shutdown_reboot_handler, channel, ACK_REQ_SYS_REBOOT);
138 register_command_handler(ack_timeout_default_handler, channel, ACK_TIMEOUT);
139
140 c_dev = create_uart_channel_dev(channel, uart_dev_name, monitor_cmd_dispatch);
141 if (c_dev == NULL)
142 return -1;
143 strncpy(c_dev->name, SERVICE_VM_NAME, CHANNEL_DEV_NAME_MAX - 1U);
144 /* TODO: will refine this connect_uart_channel_dev for pre-lauched VM later*/
145 pthread_create(&c_dev->listen_thread, NULL, connect_uart_channel_dev, c_dev);
146 pthread_create(&c_dev->pool_thread, NULL, poll_and_dispatch_uart_channel_events, c_dev);
147 }
148 return ret;
149 }
150 /**
151 * @brief Parse communication channel device type from configuration file
152 *
153 * @param dev_conf communication channel device configuration
154 */
parse_cmd_channel_conf(char * dev_conf)155 static int parse_cmd_channel_conf(char *dev_conf)
156 {
157 char *channel_name;
158 char *saveptr;
159 int ret = -1;
160
161 channel_name = strtok_r(dev_conf, ":", &saveptr);
162
163 if (strncmp(channel_name, "tty", sizeof("tty")) == 0)
164 ret = 0;
165 else
166 LOG_WRITE("Invalid channel type in config file\n");
167
168 memcpy(dev_conf, saveptr, strlen(saveptr) + 1);
169 return ret;
170 }
start_life_mngr(void)171 static int start_life_mngr(void)
172 {
173 int ret = 0;
174
175 if (!open_log("/var/log/life_mngr.log")) {
176 printf("Open log file failed\r\n");
177 return -ENOENT;
178 }
179 LOG_WRITE("------Lifecycle Manager start----------\n");
180 memset(&life_conf, 0x0, sizeof(struct life_mngr_config));
181 if (!load_config(LIFE_MNGR_CONFIG_PATH)) {
182 LOG_WRITE("Failed to load configuration file\n");
183 return -ENOENT;
184 }
185
186 if ((ret = parse_cmd_channel_conf(life_conf.dev_names)) < 0)
187 return ret;
188 if (strncmp("service_vm", life_conf.vm_type, MAX_CONFIG_VALUE_LEN) == 0) {
189 if ((ret = init_socket_server_and_shutdown_commands(true)) < 0)
190 return ret;
191 ret = init_uart_channel_devs_and_shutdown_commands(true, life_conf.dev_names);
192 } else if (strncmp("user_vm", life_conf.vm_type, MAX_CONFIG_VALUE_LEN) == 0) {
193 if ((ret = init_socket_server_and_shutdown_commands(false)) < 0)
194 return ret;
195 ret = init_uart_channel_devs_and_shutdown_commands(false, life_conf.dev_names);
196 } else {
197 LOG_WRITE("Invalid VM type in config file\n");
198 close_log();
199 return -EINVAL;
200 }
201 /* Wait all uart channel threads exit */
202 wait_uart_channel_devs_threads(channel);
203 return ret;
204 }
stop_life_mngr(void)205 static void stop_life_mngr(void)
206 {
207 deinit_uart_channel(channel);
208 deinit_socket(sock_server);
209 close_log();
210 }
main(int argc,char * argv[])211 int main(int argc, char *argv[])
212 {
213 int ret;
214
215 ret = start_life_mngr();
216 if (ret < 0) {
217 printf("Failed to start lifecycle Manager, ret=%d\n", ret);
218 return ret;
219 }
220 stop_life_mngr();
221 if (get_system_shutdown_flag()) {
222 do {
223 ret = system(POWEROFF);
224 } while (ret < 0);
225 }
226 if (get_vm_reboot_flag()) {
227 do {
228 ret = system(REBOOT);
229 } while (ret < 0);
230 }
231 return 0;
232 }
233
234