diff --git a/misc/services/life_mngr/command.c b/misc/services/life_mngr/command.c index 6625655e1..f2e276bf6 100644 --- a/misc/services/life_mngr/command.c +++ b/misc/services/life_mngr/command.c @@ -36,6 +36,7 @@ GEN_CMD_OBJ(REQ_USER_VM_REBOOT, REQ_USER_VM_REBOOT_ID), \ GEN_CMD_OBJ(USER_VM_REBOOT, USER_VM_REBOOT_ID),\ GEN_CMD_OBJ(ACK_USER_VM_REBOOT, ACK_USER_VM_REBOOT_ID),\ + GEN_CMD_OBJ(REQ_SYS_REBOOT, REQ_SYS_REBOOT_ID), \ struct command dm_command_list[CMD_END] = {CMD_OBJS}; diff --git a/misc/services/life_mngr/command.h b/misc/services/life_mngr/command.h index 6984e466e..a79f14677 100644 --- a/misc/services/life_mngr/command.h +++ b/misc/services/life_mngr/command.h @@ -19,6 +19,8 @@ #define USER_VM_SHUTDOWN "user_vm_shutdown" #define REQ_USER_VM_REBOOT "req_user_vm_reboot" #define USER_VM_REBOOT "user_vm_reboot" +#define REQ_SYS_REBOOT "req_sys_reboot" +#define ACK_REQ_SYS_REBOOT "ack_req_sys_reboot" #define ACK_REQ_USER_VM_SHUTDOWN "ack_req_user_vm_shutdown" #define ACK_USER_VM_SHUTDOWN "ack_user_vm_shutdown" @@ -49,6 +51,7 @@ enum command_id { REQ_USER_VM_REBOOT_ID, USER_VM_REBOOT_ID, ACK_USER_VM_REBOOT_ID, + REQ_SYS_REBOOT_ID, CMD_END, }; diff --git a/misc/services/life_mngr/command_handler.c b/misc/services/life_mngr/command_handler.c index fc585098e..6e1839fb6 100644 --- a/misc/services/life_mngr/command_handler.c +++ b/misc/services/life_mngr/command_handler.c @@ -26,10 +26,13 @@ bool get_system_shutdown_flag(void) } bool user_vm_reboot_flag; -bool get_user_vm_reboot_flag(void) +bool system_reboot_flag; +bool system_reboot_request_flag; +bool get_vm_reboot_flag(void) { - return user_vm_reboot_flag; + return user_vm_reboot_flag | system_reboot_flag; } + /** * @brief check whether all acrn-dm instance have been exit or not * @@ -65,6 +68,23 @@ static bool wait_post_vms_shutdown(void) } while (check_time > 0); return all_done; } +static void start_system_reboot(void) +{ + static bool platform_reboot; + + if (is_uart_channel_connection_list_empty(channel) && (!platform_reboot)) { + platform_reboot = true; + LOG_WRITE("UART connection list is empty, will trigger system reboot\n"); + close_socket(sock_server); + stop_listen_uart_channel_dev(channel); + if (wait_post_vms_shutdown()) { + LOG_WRITE("Service VM starts to reboot.\n"); + system_reboot_flag = true; + } else { + LOG_WRITE("Some User VMs failed to power off, cancelled the platform reboot process.\n"); + } + } +} static void start_system_shutdown(void) { static bool platform_shutdown; @@ -78,7 +98,7 @@ static void start_system_shutdown(void) LOG_WRITE("Service VM starts to power off.\n"); system_shutdown_flag = true; } else { - LOG_WRITE("Some User VMs failed to power off, cancelled the platform shut down process.\n"); + LOG_WRITE("Some User VMs failed to power off, cancelled the platform shutdown process.\n"); } } } @@ -207,6 +227,35 @@ int sync_cmd_handler(void *arg, int fd) usleep(2 * WAIT_RECV); return 0; } +int req_reboot_handler(void *arg, int fd) +{ + int ret; + struct channel_dev *c_dev = NULL; + struct uart_channel *c = (struct uart_channel *)arg; + + c_dev = find_uart_channel_dev(c, fd); + if (c_dev == NULL) + return 0; + + if (is_allowed_s5_channel_dev(&life_conf, c_dev)) { + LOG_PRINTF("The user VM (%s) is not allowed to trigger system reboot\n", + c_dev->name); + return 0; + } + LOG_PRINTF("Receive reboot request from user VM (%s)\n", c_dev->name); + ret = send_message_by_uart(c_dev->uart_device, ACK_REQ_SYS_REBOOT, + strlen(ACK_REQ_SYS_REBOOT)); + if (ret < 0) + LOG_WRITE("Send acked message to user VM fail\n"); + system_reboot_request_flag = true; + usleep(SECOND_TO_US); + LOG_PRINTF("Send acked shutdown request message to user VM (%s)\n", c_dev->name); + start_all_uart_channel_dev_resend(c, POWEROFF_CMD, VM_SHUTDOWN_RETRY_TIMES); + notify_all_connected_uart_channel_dev(c, POWEROFF_CMD); + usleep(2 * WAIT_RECV); + return ret; +} + /** * @brief The handler of system shutdown request command of lifecycle manager in service VM * @@ -261,7 +310,11 @@ int ack_poweroff_handler(void *arg, int fd) stop_uart_channel_dev_resend(c_dev); disconnect_uart_channel_dev(c_dev, c); usleep(WAIT_USER_VM_POWEROFF); - start_system_shutdown(); + if (system_reboot_request_flag) { + start_system_reboot(); + } else { + start_system_shutdown(); + } return 0; } /** diff --git a/misc/services/life_mngr/command_handler.h b/misc/services/life_mngr/command_handler.h index e232831d7..45e85e6dd 100644 --- a/misc/services/life_mngr/command_handler.h +++ b/misc/services/life_mngr/command_handler.h @@ -16,7 +16,7 @@ bool get_system_shutdown_flag(void); /** * @brief Get the reboot flag */ -bool get_user_vm_reboot_flag(void); +bool get_vm_reboot_flag(void); /** * @brief The handler of request system shutdown command on socket in service VM */ @@ -50,6 +50,14 @@ int sync_cmd_handler(void *arg, int fd); * @return indicate this command is handled successful or not */ int req_shutdown_handler(void *arg, int fd); +/** + * @brief The handler of system reboot request command of lifecycle manager in service VM + * + * @param arg uart channel device instance + * @param fd the file directory of the uart which receives message + * @return indicate this command is handled successful or not + */ +int req_reboot_handler(void *arg, int fd); /** * @brief The handler of acked poweroff command of lifecycle manager in service VM * diff --git a/misc/services/life_mngr/life_mngr_win.c b/misc/services/life_mngr/life_mngr_win.c index 3b67023ae..7a6614981 100644 --- a/misc/services/life_mngr/life_mngr_win.c +++ b/misc/services/life_mngr/life_mngr_win.c @@ -20,6 +20,8 @@ #define ACK_USER_VM_SHUTDOWN "ack_user_vm_shutdown" #define USER_VM_REBOOT "user_vm_reboot" #define ACK_USER_VM_REBOOT "ack_user_vm_reboot" +#define REQ_SYS_REBOOT "req_sys_reboot" +#define ACK_REQ_SYS_REBOOT "ack_req_sys_reboot" #define SYNC_FMT "sync:%s" #define S5_REJECTED "system shutdown request is rejected" @@ -122,6 +124,10 @@ DWORD WINAPI open_socket_server(LPVOID lpParam) handle_socket_request(sClient, REQ_SYS_SHUTDOWN); break; } + if (strncmp(revData, REQ_SYS_REBOOT, sizeof(REQ_SYS_REBOOT)) == 0) { + handle_socket_request(sClient, REQ_SYS_REBOOT); + break; + } } while (1); closesocket(sClient); sock_exit: @@ -234,6 +240,9 @@ int main() } else if (strncmp(recvbuf, ACK_REQ_SYS_SHUTDOWN, sizeof(ACK_REQ_SYS_SHUTDOWN)) == 0) { stop_uart_resend(); printf("Received acked system shutdown request from service VM\n"); + } else if (strncmp(recvbuf, ACK_REQ_SYS_REBOOT, sizeof(ACK_REQ_SYS_REBOOT)) == 0) { + stop_uart_resend(); + printf("Received acked system reboot request from service VM\n"); } else if (strncmp(recvbuf, POWEROFF_CMD, sizeof(POWEROFF_CMD)) == 0) { printf("Received system shutdown message from service VM\n"); send_message_by_uart(hCom2, ACK_POWEROFF, sizeof(ACK_POWEROFF)); diff --git a/misc/services/life_mngr/monitor.c b/misc/services/life_mngr/monitor.c index 1dbeddb57..81e44dfb8 100644 --- a/misc/services/life_mngr/monitor.c +++ b/misc/services/life_mngr/monitor.c @@ -117,6 +117,7 @@ int init_uart_channel_devs_and_shutdown_commands(bool service_vm, char *uart_dev if (service_vm) { register_command_handler(sync_cmd_handler, channel, SYNC_CMD); register_command_handler(req_shutdown_handler, channel, REQ_SYS_SHUTDOWN); + register_command_handler(req_reboot_handler, channel, REQ_SYS_REBOOT); register_command_handler(ack_poweroff_handler, channel, ACK_POWEROFF); register_command_handler(ack_timeout_handler, channel, ACK_TIMEOUT); register_command_handler(ack_user_vm_shutdown_cmd_handler, channel, ACK_USER_VM_SHUTDOWN); @@ -219,7 +220,7 @@ int main(int argc, char *argv[]) ret = system(POWEROFF); } while (ret < 0); } - if (get_user_vm_reboot_flag()) { + if (get_vm_reboot_flag()) { do { ret = system(REBOOT); } while (ret < 0); diff --git a/misc/services/life_mngr/system_reboot_trigger_win.py b/misc/services/life_mngr/system_reboot_trigger_win.py new file mode 100644 index 000000000..aa6b9a4df --- /dev/null +++ b/misc/services/life_mngr/system_reboot_trigger_win.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 Intel Corporation. +# +# SPDX-License-Identifier: BSD-3-Clause +# +import socket +import sys + +if __name__ == "__main__": + HOST = '127.0.0.1' + PORT = 8193 + SYS_REBOOT_REQ = 'req_sys_reboot' + MSG_LEN = 32 + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + print(["Socket Created"]) + + try: + s.connect((HOST,PORT)) + print("[Connection established]") + except Exception: + print('[Connection error: ' + HOST + ":" + str(PORT)+']') + s.close() + + try: + s.send(SYS_REBOOT_REQ.encode('utf-8')) + except Exception as _: + raise _ + print(["System reboot request sent\n"]) + + try: + data_input = (s.recv(MSG_LEN).decode("UTF-8")) + except Exception: + pass + print("Waiting for ACK message...: ", data_input) + s.close()