1 /*
2  * Copyright (C)2021-2022 Intel Corporation.
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdbool.h>
9 #include <unistd.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 #include <sys/un.h>
13 #include <libgen.h>
14 #include "uart.h"
15 #include "uart_channel.h"
16 #include "command.h"
17 #include "socket.h"
18 #include "command_handler.h"
19 #include "log.h"
20 #include "config.h"
21 
22 bool system_shutdown_flag;
get_system_shutdown_flag(void)23 bool get_system_shutdown_flag(void)
24 {
25 	return system_shutdown_flag;
26 }
27 
28 bool user_vm_reboot_flag;
29 bool system_reboot_flag;
30 bool system_reboot_request_flag;
get_vm_reboot_flag(void)31 bool get_vm_reboot_flag(void)
32 {
33 	return user_vm_reboot_flag | system_reboot_flag;
34 }
35 
36 /**
37  * @brief check whether all acrn-dm instance have been exit or not
38  *
39  * @return true all acrn-dm instance have been exit
40  * @return false at least one acrn-dm exist
41  */
wait_post_vms_shutdown(void)42 static bool wait_post_vms_shutdown(void)
43 {
44 	FILE *fp = NULL;
45 	char command[64], buf[8];
46 	char *endptr, *ret_str;
47 	long val;
48 	int check_time = SHUTDOWN_TIMEOUT/5;
49 	bool all_done = false;
50 
51 	snprintf(command, sizeof(command), "pgrep -u root -f acrn-dm | wc -l");
52 	do {
53 		fp = popen(command, "r");
54 		ret_str = fgets(buf, sizeof(buf), fp);
55 		if (ret_str == NULL)
56 			LOG_WRITE("Failed to check acrn-dm process\n");
57 		val = strtol(buf, &endptr, 10) - 1;
58 		if (val == 0) {
59 			all_done = true;
60 			pclose(fp);
61 			break;
62 		}
63 		check_time--;
64 		LOG_PRINTF("Wait post launched VMs shutdown check_time:%d, Running VM num:%ld\n",
65 				check_time, val);
66 		pclose(fp);
67 		sleep(5);
68 	} while (check_time > 0);
69 	return all_done;
70 }
start_system_reboot(void)71 static void start_system_reboot(void)
72 {
73 	static bool platform_reboot;
74 
75 	if (is_uart_channel_connection_list_empty(channel) && (!platform_reboot)) {
76 		platform_reboot = true;
77 		LOG_WRITE("UART connection list is empty, will trigger system reboot\n");
78 		close_socket(sock_server);
79 		stop_listen_uart_channel_dev(channel);
80 		if (wait_post_vms_shutdown()) {
81 			LOG_WRITE("Service VM starts to reboot.\n");
82 			system_reboot_flag = true;
83 		} else {
84 			LOG_WRITE("Some User VMs failed to power off, cancelled the platform reboot process.\n");
85 		}
86 	}
87 }
start_system_shutdown(void)88 static void start_system_shutdown(void)
89 {
90 	static bool platform_shutdown;
91 
92 	if (is_uart_channel_connection_list_empty(channel) && (!platform_shutdown)) {
93 		platform_shutdown = true;
94 		LOG_WRITE("UART connection list is empty, will trigger shutdown system\n");
95 		close_socket(sock_server);
96 		stop_listen_uart_channel_dev(channel);
97 		if (wait_post_vms_shutdown()) {
98 			LOG_WRITE("Service VM starts to power off.\n");
99 			system_shutdown_flag = true;
100 		} else {
101 			LOG_WRITE("Some User VMs failed to power off, cancelled the platform shutdown process.\n");
102 		}
103 	}
104 }
105 
send_socket_ack(void * arg,int fd,char * ack)106 static int send_socket_ack(void *arg, int fd, char *ack)
107 {
108 	int ret = 0;
109 	struct socket_dev *sock = (struct socket_dev *)arg;
110 	struct socket_client *client = NULL;
111 
112 	client = find_socket_client(sock, fd);
113 	if (client == NULL)
114 		return -1;
115 
116 	LOG_PRINTF("Receive shutdown request from unix socket, fd=%d\n", client->fd);
117 	memset(client->buf, 0, CLIENT_BUF_LEN);
118 	memcpy(client->buf, ack, strlen(ack));
119 	client->len = strlen(ack);
120 	ret = write_socket_char(client);
121 	LOG_PRINTF("Send acked message to unix socket, message=%s\n", ack);
122 	return ret;
123 }
socket_req_shutdown_service_vm_handler(void * arg,int fd)124 int socket_req_shutdown_service_vm_handler(void *arg, int fd)
125 {
126 	int ret;
127 
128 	usleep(LISTEN_INTERVAL + SECOND_TO_US);
129 	ret = send_socket_ack(arg, fd, ACK_REQ_SYS_SHUTDOWN);
130 	if (ret < 0)
131 		return 0;
132 	start_all_uart_channel_dev_resend(channel, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES);
133 	notify_all_connected_uart_channel_dev(channel, POWEROFF_CMD);
134 	start_system_shutdown();
135 	return 0;
136 }
req_user_vm_shutdown_reboot(void * arg,int fd,char * msg,char * ack_msg)137 static int req_user_vm_shutdown_reboot(void *arg, int fd, char *msg, char *ack_msg)
138 {
139 	int ret;
140 	struct channel_dev *c_dev = NULL;
141 	struct socket_dev *sock = (struct socket_dev *)arg;
142 	struct socket_client *client = NULL;
143 
144 	usleep(LISTEN_INTERVAL + SECOND_TO_US);
145 	client = find_socket_client(sock, fd);
146 	if (client == NULL)
147 		return -1;
148 
149 	c_dev = find_uart_channel_dev_by_name(channel, client->name);
150 	if (c_dev == NULL) {
151 		(void) send_socket_ack(arg, fd, USER_VM_DISCONNECT);
152 		LOG_PRINTF("Failed to fail to find uart device to communicate with user VM (%s)\n",
153 					client->name);
154 		return 0;
155 	}
156 	ret = send_socket_ack(arg, fd, ack_msg);
157 	if (ret < 0) {
158 		LOG_WRITE("Failed to send ACK by socket\n");
159 		return 0;
160 	}
161 	LOG_PRINTF("Foward (%s) to user VM (%s) by UART\n", msg, c_dev->name);
162 	start_uart_channel_dev_resend(c_dev, msg, MIN_RESEND_TIME);
163 	ret = send_message_by_uart(c_dev->uart_device, msg, strlen(msg));
164 	if (ret < 0)
165 		LOG_PRINTF("Failed to foward (%s) to user VM by UART\n", msg);
166 	return ret;
167 }
socket_req_user_vm_shutdown_handler(void * arg,int fd)168 int socket_req_user_vm_shutdown_handler(void *arg, int fd)
169 {
170 	return req_user_vm_shutdown_reboot(arg, fd, USER_VM_SHUTDOWN, ACK_REQ_USER_VM_SHUTDOWN);
171 }
socket_req_user_vm_reboot_handler(void * arg,int fd)172 int socket_req_user_vm_reboot_handler(void *arg, int fd)
173 {
174 	return req_user_vm_shutdown_reboot(arg, fd, USER_VM_REBOOT, ACK_REQ_USER_VM_REBOOT);
175 }
176 
req_system_shutdown_reboot(void * arg,int fd,char * msg,char * ack_msg)177 int req_system_shutdown_reboot(void *arg, int fd, char *msg, char *ack_msg)
178 {
179 	int ret;
180 	struct channel_dev *c_dev = NULL;
181 
182 	usleep(LISTEN_INTERVAL + SECOND_TO_US);
183 	c_dev = (struct channel_dev *)LIST_FIRST(&channel->tty_conn_head);
184 	if (c_dev == NULL) {
185 		(void) send_socket_ack(arg, fd, USER_VM_DISCONNECT);
186 		LOG_WRITE("User VM is disconnect\n");
187 		return 0;
188 	}
189 
190 	ret = send_socket_ack(arg, fd, ack_msg);
191 	if (ret < 0) {
192 		LOG_WRITE("Failed to send ACK by socket\n");
193 		return 0;
194 	}
195 	LOG_PRINTF("Foward (%s) req to service VM by UART\n", msg);
196 	start_uart_channel_dev_resend(c_dev, msg, MIN_RESEND_TIME);
197 	ret = send_message_by_uart(c_dev->uart_device, msg, strlen(msg));
198 	if (ret < 0)
199 		LOG_PRINTF("Failed to foward (%s) to service VM by UART\n", msg);
200 	return ret;
201 }
202 
socket_req_system_reboot_user_vm_handler(void * arg,int fd)203 int socket_req_system_reboot_user_vm_handler(void *arg, int fd)
204 {
205 	return req_system_shutdown_reboot(arg, fd, REQ_SYS_REBOOT, ACK_REQ_SYS_REBOOT);
206 	}
207 
socket_req_system_shutdown_user_vm_handler(void * arg,int fd)208 int socket_req_system_shutdown_user_vm_handler(void *arg, int fd)
209 {
210 	return req_system_shutdown_reboot(arg, fd, REQ_SYS_SHUTDOWN, ACK_REQ_SYS_SHUTDOWN);
211 }
212 
is_allowed_s5_channel_dev(struct life_mngr_config * conf,struct channel_dev * c_dev)213 static int is_allowed_s5_channel_dev(struct life_mngr_config *conf, struct channel_dev *c_dev)
214 {
215 	return strncmp(get_allow_s5_config(conf), get_uart_dev_path(c_dev->uart_device),
216 					TTY_PATH_MAX);
217 }
218 
is_allowed_sysreboot_channel_dev(struct life_mngr_config * conf,struct channel_dev * c_dev)219 static int is_allowed_sysreboot_channel_dev(struct life_mngr_config *conf, struct channel_dev *c_dev)
220 {
221 	return strncmp(get_allow_sysreboot_config(conf), get_uart_dev_path(c_dev->uart_device),
222 					TTY_PATH_MAX);
223 }
224 
225 /**
226  * @brief The handler of sync command of lifecycle manager in service VM
227  *
228  * @param arg uart channel device instance
229  * @param fd the file directory of the uart which receives message
230  * @return indicate this command is handled successful or not
231  */
sync_cmd_handler(void * arg,int fd)232 int sync_cmd_handler(void *arg, int fd)
233 {
234 	struct channel_dev *c_dev = NULL;
235 	struct uart_channel *c = (struct uart_channel *)arg;
236 
237 	c_dev = find_uart_channel_dev(c, fd);
238 	if (c_dev == NULL)
239 		return 0;
240 
241 	(void)send_message_by_uart(c_dev->uart_device, ACK_SYNC, strlen(ACK_SYNC));
242 	LOG_PRINTF("Receive sync message from user VM (%s), start to talk.\n",
243 		c_dev->name);
244 	usleep(2 * WAIT_RECV);
245 	return 0;
246 }
req_reboot_handler(void * arg,int fd)247 int req_reboot_handler(void *arg, int fd)
248 {
249 	int ret;
250 	struct channel_dev *c_dev = NULL;
251 	struct uart_channel *c = (struct uart_channel *)arg;
252 
253 	c_dev = find_uart_channel_dev(c, fd);
254 	if (c_dev == NULL)
255 		return 0;
256 
257 	if (is_allowed_sysreboot_channel_dev(&life_conf, c_dev)) {
258 		LOG_PRINTF("The user VM (%s) is not allowed to trigger system reboot\n",
259 			c_dev->name);
260 		return 0;
261 	}
262 	LOG_PRINTF("Receive reboot request from user VM (%s)\n", c_dev->name);
263 	ret = send_message_by_uart(c_dev->uart_device, ACK_REQ_SYS_REBOOT,
264 								strlen(ACK_REQ_SYS_REBOOT));
265 	if (ret < 0)
266 		LOG_WRITE("Sending a reboot acknowledgement message to user VM failed.\n");
267 	system_reboot_request_flag = true;
268 	usleep(SECOND_TO_US);
269 	LOG_PRINTF("Send acked shutdown request message to user VM (%s)\n", c_dev->name);
270 	start_all_uart_channel_dev_resend(c, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES);
271 	notify_all_connected_uart_channel_dev(c, POWEROFF_CMD);
272 	usleep(2 * WAIT_RECV);
273 	return ret;
274 }
275 
276 /**
277  * @brief The handler of system shutdown request command of lifecycle manager in service VM
278  *
279  * @param arg uart channel device instance
280  * @param fd the file directory of the uart which receives message
281  * @return indicate this command is handled successful or not
282  */
req_shutdown_handler(void * arg,int fd)283 int req_shutdown_handler(void *arg, int fd)
284 {
285 	int ret;
286 	struct channel_dev *c_dev = NULL;
287 	struct uart_channel *c = (struct uart_channel *)arg;
288 
289 	c_dev = find_uart_channel_dev(c, fd);
290 	if (c_dev == NULL)
291 		return 0;
292 
293 	if (is_allowed_s5_channel_dev(&life_conf, c_dev)) {
294 		LOG_PRINTF("The user VM (%s) is not allowed to trigger system shutdown\n",
295 			c_dev->name);
296 		return 0;
297 	}
298 	LOG_PRINTF("Receive shutdown request from user VM (%s)\n", c_dev->name);
299 	ret = send_message_by_uart(c_dev->uart_device, ACK_REQ_SYS_SHUTDOWN,
300 								strlen(ACK_REQ_SYS_SHUTDOWN));
301 	if (ret < 0)
302 		LOG_WRITE("Sending a shutdown acknowledgement message to user VM failed.\n");
303 	usleep(SECOND_TO_US);
304 	LOG_PRINTF("Send acked shutdown request message to user VM (%s)\n", c_dev->name);
305 	start_all_uart_channel_dev_resend(c, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES);
306 	notify_all_connected_uart_channel_dev(c, POWEROFF_CMD);
307 	usleep(2 * WAIT_RECV);
308 	return ret;
309 }
310 
311 /**
312  * @brief The handler of acked poweroff command of lifecycle manager in service VM
313  *
314  * @param arg uart channel instance
315  * @param fd the file directory of the uart which receives message
316  * @return indicate this command is handled successful or not
317  */
ack_poweroff_handler(void * arg,int fd)318 int ack_poweroff_handler(void *arg, int fd)
319 {
320 	struct channel_dev *c_dev = NULL;
321 	struct uart_channel *c = (struct uart_channel *)arg;
322 
323 	c_dev = find_uart_channel_dev(c, fd);
324 	if (c_dev == NULL)
325 		return 0;
326 	LOG_PRINTF("Receive poweroff ACK from user VM (%s)\n", c_dev->name);
327 	stop_uart_channel_dev_resend(c_dev);
328 	disconnect_uart_channel_dev(c_dev, c);
329 	usleep(WAIT_USER_VM_POWEROFF);
330 	if (system_reboot_request_flag) {
331 		start_system_reboot();
332 	} else {
333 		start_system_shutdown();
334 	}
335 	return 0;
336 }
337 /**
338  * @brief The handler of ACK timeout command of lifecycle manager in service VM
339  *
340  * @param arg uart channel instance
341  * @param fd the file directory of the uart which receives message
342  * @return indicate this command is handled successful or not
343  */
ack_timeout_handler(void * arg,int fd)344 int ack_timeout_handler(void *arg, int fd)
345 {
346 	struct channel_dev *c_dev = NULL;
347 	struct uart_channel *c = (struct uart_channel *)arg;
348 
349 	c_dev = find_uart_channel_dev(c, fd);
350 	if (c_dev == NULL)
351 		return 0;
352 	if (strncmp(c_dev->resend_buf, POWEROFF_CMD, strlen(POWEROFF_CMD)) == 0)
353 		ack_poweroff_handler(arg, fd);
354 	else
355 		stop_uart_channel_dev_resend(c_dev);
356 	return 0;
357 }
ack_user_vm_cmd(void * arg,int fd,char * ack_msg)358 static int ack_user_vm_cmd(void *arg, int fd, char *ack_msg)
359 {
360 	struct channel_dev *c_dev = NULL;
361 	struct uart_channel *c = (struct uart_channel *)arg;
362 
363 	c_dev = find_uart_channel_dev(c, fd);
364 	if (c_dev == NULL)
365 		return 0;
366 	LOG_PRINTF("Receive (%s) from user VM (%s)\n", ack_msg, c_dev->name);
367 	stop_uart_channel_dev_resend(c_dev);
368 	return 0;
369 }
ack_user_vm_shutdown_cmd_handler(void * arg,int fd)370 int ack_user_vm_shutdown_cmd_handler(void *arg, int fd)
371 {
372 	return ack_user_vm_cmd(arg, fd, ACK_USER_VM_SHUTDOWN);
373 }
374 
ack_user_vm_reboot_cmd_handler(void * arg,int fd)375 int ack_user_vm_reboot_cmd_handler(void *arg, int fd)
376 {
377 	return ack_user_vm_cmd(arg, fd, ACK_USER_VM_REBOOT);
378 }
379 /**
380  * @brief The handler of acked sync command of lifecycle manager in user VM
381  *
382  * @param arg uart channel device instance
383  * @param fd the file directory of the uart which receives message
384  * @return indicate this command is handled successful or not
385  */
acked_sync_handler(void * arg,int fd)386 int acked_sync_handler(void *arg, int fd)
387 {
388 	struct channel_dev *c_dev = NULL;
389 	struct uart_channel *c = (struct uart_channel *)arg;
390 
391 	c_dev = find_uart_channel_dev(c, fd);
392 	if (c_dev == NULL)
393 		return 0;
394 	LOG_WRITE("Receive acked sync message from service VM\n");
395 	return 0;
396 }
397 
398 /**
399  * @brief The handler of acked system shutdown request command of lifecycle manager in user VM
400  *
401  * @param arg uart channel instance
402  * @param fd the file directory of the uart which receives message
403  * @return indicate this command is handled successful or not
404  */
acked_req_shutdown_reboot_handler(void * arg,int fd)405 int acked_req_shutdown_reboot_handler(void *arg, int fd)
406 {
407 	struct channel_dev *c_dev = NULL;
408 	struct uart_channel *c = (struct uart_channel *)arg;
409 
410 	c_dev = find_uart_channel_dev(c, fd);
411 	if (c_dev == NULL)
412 		return 0;
413 	stop_uart_channel_dev_resend(c_dev);
414 	LOG_WRITE("Receive shutdown request ACK from service VM\n");
415 	return 0;
416 }
user_vm_shutdown_reboot(struct uart_channel * c,int fd,char * ack,bool reboot)417 static int user_vm_shutdown_reboot(struct uart_channel *c, int fd, char *ack, bool reboot)
418 {
419 	int ret;
420 	struct channel_dev *c_dev = NULL;
421 
422 	c_dev = find_uart_channel_dev(c, fd);
423 	if (c_dev == NULL)
424 		return 0;
425 
426 	ret = send_message_by_uart(c_dev->uart_device, ack, strlen(ack));
427 	if (ret < 0) {
428 		LOG_PRINTF("Failed to send (%s) to service VM\n", ack);
429 	}
430 	disconnect_uart_channel_dev(c_dev, c);
431 	usleep(2 * WAIT_RECV);
432 	close_socket(sock_server);
433 	if (reboot) {
434 		user_vm_reboot_flag = true;
435 	} else {
436 		system_shutdown_flag = true;
437 	}
438 	return 0;
439 }
440 /**
441  * @brief The handler of poweroff command of lifecycle manager in user VM
442  *
443  * @param arg uart channel device instance
444  * @param fd the file directory of the uart which receives message
445  * @return indicate this command is handled successful or not
446  */
poweroff_cmd_handler(void * arg,int fd)447 int poweroff_cmd_handler(void *arg, int fd)
448 {
449 
450 	struct uart_channel *c = (struct uart_channel *)arg;
451 	(void) user_vm_shutdown_reboot(c, fd, ACK_POWEROFF, false);
452 	return 0;
453 }
user_vm_shutdown_cmd_handler(void * arg,int fd)454 int user_vm_shutdown_cmd_handler(void *arg, int fd)
455 {
456 	struct uart_channel *c = (struct uart_channel *)arg;
457 	(void) user_vm_shutdown_reboot(c, fd, ACK_USER_VM_SHUTDOWN, false);
458 	return 0;
459 }
user_vm_reboot_cmd_handler(void * arg,int fd)460 int user_vm_reboot_cmd_handler(void *arg, int fd)
461 {
462 	struct uart_channel *c = (struct uart_channel *)arg;
463 	(void) user_vm_shutdown_reboot(c, fd, ACK_USER_VM_REBOOT, true);
464 	return 0;
465 }
466 /**
467  * @brief The handler of ACK timeout command of lifecycle manager in user VM
468  *
469  * @param arg uart channel instance
470  * @param fd the file directory of the uart which receives message
471  * @return indicate this command is handled successful or not
472  */
ack_timeout_default_handler(void * arg,int fd)473 int ack_timeout_default_handler(void *arg, int fd)
474 {
475 	struct channel_dev *c_dev = NULL;
476 	struct uart_channel *c = (struct uart_channel *)arg;
477 
478 	c_dev = find_uart_channel_dev(c, fd);
479 	if (c_dev == NULL)
480 		return 0;
481 	stop_uart_channel_dev_resend(c_dev);
482 	disconnect_uart_channel_dev(c_dev, c);
483 	close_socket(sock_server);
484 	LOG_PRINTF("Failed to receive ACK message from service VM (fd = %d)\n", fd);
485 	return 0;
486 }
487