1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <sys/param.h>
8 #include <sys/stat.h>
9 #include <errno.h>
10 #include <paths.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <stdbool.h>
17 #include <fcntl.h>
18 
19 #include "log.h"
20 
21 #define KMSG_DEV_NODE "/dev/kmsg"
22 #define KMSG_PREFIX  "acrn_dm: "
23 
24 #define KMSG_MAX_LEN    (MAX_ONE_LOG_SIZE + 64)
25 #define DEFAULT_KMSG_LEVEL    LOG_NOTICE
26 
27 static int kmsg_fd = -1;
28 
29 static uint8_t kmsg_log_level = DEFAULT_KMSG_LEVEL;
30 static bool kmsg_enabled = false;
31 
is_kmsg_enabled(void)32 static bool is_kmsg_enabled(void)
33 {
34 	return kmsg_enabled;
35 }
36 
get_kmsg_log_level(void)37 static uint8_t get_kmsg_log_level(void)
38 {
39 	return kmsg_log_level;
40 }
41 
init_kmsg_logger(bool enable,uint8_t log_level)42 static int init_kmsg_logger(bool enable, uint8_t log_level)
43 {
44 	kmsg_enabled = enable;
45 	kmsg_log_level = log_level;
46 
47 	/* usually this init should be called once in DM whole life */
48 	if (kmsg_fd > 0)
49 		return kmsg_fd;
50 
51 	kmsg_fd = open(KMSG_DEV_NODE, O_RDWR | O_APPEND | O_NONBLOCK);
52 	if (kmsg_fd < 0) {
53 		kmsg_enabled = false;
54 		pr_err(KMSG_PREFIX"open kmsg dev failed");
55 	}
56 
57 	return kmsg_fd;
58 }
59 
deinit_kmsg(void)60 static void deinit_kmsg(void)
61 {
62 	if (kmsg_fd > 0) {
63 		close(kmsg_fd);
64 		kmsg_fd = -1;
65 
66 		kmsg_enabled = false;
67 	}
68 }
69 
write_to_kmsg(const char * fmt,va_list args)70 static void write_to_kmsg(const char *fmt, va_list args)
71 {
72 	char *buf;
73 	char kmsg_buf[KMSG_MAX_LEN] = KMSG_PREFIX;
74 	int len, write_cnt;
75 
76 	if (kmsg_fd < 0)
77 		return;
78 
79 	len = vasprintf(&buf, fmt, args);
80 	if (len < 0)
81 		return;
82 	strncpy(kmsg_buf + strlen(KMSG_PREFIX), buf, KMSG_MAX_LEN - strlen(KMSG_PREFIX));
83 	kmsg_buf[KMSG_MAX_LEN - 1] = '\0';
84 	free(buf);
85 
86 	write_cnt = write(kmsg_fd, kmsg_buf, strnlen(kmsg_buf, KMSG_MAX_LEN));
87 	if (write_cnt < 0) {
88 		pr_err(KMSG_PREFIX"write kmsg failed");
89 		close(kmsg_fd);
90 		kmsg_fd = -1;
91 	}
92 }
93 
94 static struct logger_ops logger_kmsg = {
95 	.name = "kmsg",
96 	.is_enabled = is_kmsg_enabled,
97 	.get_log_level = get_kmsg_log_level,
98 	.init = init_kmsg_logger,
99 	.deinit = deinit_kmsg,
100 	.output = write_to_kmsg,
101 };
102 
103 DEFINE_LOGGER_DEVICE(logger_kmsg);
104