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/socket.h>
16 #include <pthread.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <sys/un.h>
20 #include "command.h"
21 #include "log.h"
22
23 #define GEN_CMD_OBJ(cmd_name, cmd_id) \
24 {.name = cmd_name, .id = cmd_id, .cmd_handler_mtx = PTHREAD_MUTEX_INITIALIZER}
25 #define CMD_OBJS \
26 GEN_CMD_OBJ(SYNC_CMD, SYNC_ID), \
27 GEN_CMD_OBJ(ACK_SYNC, ACKED_SYNC_ID), \
28 GEN_CMD_OBJ(REQ_SYS_SHUTDOWN, REQ_SYS_SHUTDOWN_ID), \
29 GEN_CMD_OBJ(ACK_REQ_SYS_SHUTDOWN, ACKED_REQ_SYS_SHUTDOWN_ID), \
30 GEN_CMD_OBJ(POWEROFF_CMD, POWEROFF_CMD_ID), \
31 GEN_CMD_OBJ(ACK_POWEROFF, ACKED_POWEROFF_ID), \
32 GEN_CMD_OBJ(ACK_TIMEOUT, ACK_TIMEOUT_ID), \
33 GEN_CMD_OBJ(REQ_USER_VM_SHUTDOWN, REQ_USER_VM_SHUTDOWN_ID), \
34 GEN_CMD_OBJ(USER_VM_SHUTDOWN, USER_VM_SHUTDOWN_ID),\
35 GEN_CMD_OBJ(ACK_USER_VM_SHUTDOWN, ACK_USER_VM_SHUTDOWN_ID),\
36 GEN_CMD_OBJ(REQ_USER_VM_REBOOT, REQ_USER_VM_REBOOT_ID), \
37 GEN_CMD_OBJ(USER_VM_REBOOT, USER_VM_REBOOT_ID),\
38 GEN_CMD_OBJ(ACK_USER_VM_REBOOT, ACK_USER_VM_REBOOT_ID),\
39 GEN_CMD_OBJ(REQ_SYS_REBOOT, REQ_SYS_REBOOT_ID), \
40 GEN_CMD_OBJ(ACK_REQ_SYS_REBOOT, ACK_REQ_SYS_REBOOT_ID), \
41
42 struct command dm_command_list[CMD_END] = {CMD_OBJS};
43
dispatch_command_handlers(void * arg,int fd)44 int dispatch_command_handlers(void *arg, int fd)
45 {
46 struct command *cmd = (struct command *)arg;
47 struct command_handlers *handler;
48 unsigned int count = 0U;
49 int ret = 0;
50
51 if (cmd == NULL) {
52 LOG_PRINTF("Invalid command, fd=%d\n", fd);
53 return -EINVAL;
54 }
55 LOG_PRINTF("Handle command (%s) in command monitor\n", cmd->name);
56 LIST_FOREACH(handler, &cmd->cmd_handlers_head, list) {
57 if (handler->fn) {
58 ret = handler->fn(handler->arg, fd);
59 count++;
60 }
61 }
62 LOG_PRINTF("Command handler ret=%d\n", ret);
63 if (!count)
64 LOG_PRINTF("No handler for command:%s\r\n", cmd->name);
65 return 0;
66 }
find_command(const char * name)67 struct command *find_command(const char *name)
68 {
69 for (int i = 0; (i < CMD_END) && (name != NULL); i++) {
70 if (strcmp(dm_command_list[i].name, name) == 0)
71 return &dm_command_list[i];
72 }
73 return NULL;
74 }
75
register_command_handler(cmd_handler * fn,void * arg,const char * cmd_name)76 int register_command_handler(cmd_handler *fn, void *arg, const char *cmd_name)
77 {
78 struct command *cmd;
79 struct command_handlers *handler;
80
81 if ((!fn) || (!arg) || (!cmd_name)) {
82 LOG_PRINTF("%s:Failed to register command_handler\n", __func__);
83 return -EINVAL;
84 }
85 cmd = find_command(cmd_name);
86 if (cmd == NULL) {
87 LOG_PRINTF("%s:invalid command name (%s)\r\n", __func__, cmd_name);
88 return -EINVAL;
89 }
90
91 handler = calloc(1, sizeof(*handler));
92 if (!handler) {
93 LOG_WRITE("Failed to allocate command handler\r\n");
94 return -ENOMEM;
95 }
96
97 handler->fn = fn;
98 handler->arg = arg;
99
100 pthread_mutex_lock(&cmd->cmd_handler_mtx);
101 LIST_INSERT_HEAD(&cmd->cmd_handlers_head, handler, list);
102 pthread_mutex_unlock(&cmd->cmd_handler_mtx);
103
104 return 0;
105 }
106