1 /*
2  * Copyright (c) 2020 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/kernel.h>
7 #include <zephyr/syscall_handler.h>
8 #include <zephyr/logging/log_internal.h>
9 #include <zephyr/logging/log_ctrl.h>
10 #include <zephyr/logging/log_frontend.h>
11 #include <zephyr/logging/log_backend.h>
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_DECLARE(log);
14 
15 BUILD_ASSERT(sizeof(struct log_msg_desc) == sizeof(uint32_t),
16 	     "Descriptor must fit in 32 bits");
17 
18 /* Returns true if any backend is in use. */
19 #define BACKENDS_IN_USE() \
20 	!(IS_ENABLED(CONFIG_LOG_FRONTEND) && \
21 	 (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY) || log_backend_count_get() == 0))
22 
z_log_msg_finalize(struct log_msg * msg,const void * source,const struct log_msg_desc desc,const void * data)23 void z_log_msg_finalize(struct log_msg *msg, const void *source,
24 			 const struct log_msg_desc desc, const void *data)
25 {
26 	if (!msg) {
27 		z_log_dropped(false);
28 
29 		return;
30 	}
31 
32 	if (data) {
33 		uint8_t *d = msg->data + desc.package_len;
34 
35 		memcpy(d, data, desc.data_len);
36 	}
37 
38 	msg->hdr.desc = desc;
39 	msg->hdr.source = source;
40 	z_log_msg_commit(msg);
41 }
42 
z_impl_z_log_msg_static_create(const void * source,const struct log_msg_desc desc,uint8_t * package,const void * data)43 void z_impl_z_log_msg_static_create(const void *source,
44 			      const struct log_msg_desc desc,
45 			      uint8_t *package, const void *data)
46 {
47 	if (IS_ENABLED(CONFIG_LOG_FRONTEND)) {
48 		log_frontend_msg(source, desc, package, data);
49 	}
50 
51 	if (!BACKENDS_IN_USE()) {
52 		return;
53 	}
54 
55 	struct log_msg_desc out_desc = desc;
56 	int inlen = desc.package_len;
57 	struct log_msg *msg;
58 
59 	if (inlen > 0) {
60 		uint32_t flags = CBPRINTF_PACKAGE_CONVERT_RW_STR |
61 				 CBPRINTF_PACKAGE_CONVERT_PTR_CHECK;
62 		uint16_t strl[4];
63 		int len;
64 
65 		len = cbprintf_package_copy(package, inlen,
66 					    NULL, 0, flags,
67 					    strl, ARRAY_SIZE(strl));
68 
69 		if (len > Z_LOG_MSG_MAX_PACKAGE) {
70 			struct cbprintf_package_hdr_ext *pkg =
71 				(struct cbprintf_package_hdr_ext *)package;
72 
73 			LOG_WRN("Message (\"%s\") dropped because it exceeds size limitation (%u)",
74 				pkg->fmt, (uint32_t)Z_LOG_MSG_MAX_PACKAGE);
75 			return;
76 		}
77 		/* Update package length with calculated value (which may be extended
78 		 * when strings are copied into the package.
79 		 */
80 		out_desc.package_len = len;
81 		msg = z_log_msg_alloc(log_msg_get_total_wlen(out_desc));
82 		if (msg) {
83 			len = cbprintf_package_copy(package, inlen,
84 						    msg->data, out_desc.package_len,
85 						    flags, strl, ARRAY_SIZE(strl));
86 			__ASSERT_NO_MSG(len >= 0);
87 		}
88 	} else {
89 		msg = z_log_msg_alloc(log_msg_get_total_wlen(out_desc));
90 	}
91 
92 	z_log_msg_finalize(msg, source, out_desc, data);
93 }
94 
95 #ifdef CONFIG_USERSPACE
z_vrfy_z_log_msg_static_create(const void * source,const struct log_msg_desc desc,uint8_t * package,const void * data)96 static inline void z_vrfy_z_log_msg_static_create(const void *source,
97 			      const struct log_msg_desc desc,
98 			      uint8_t *package, const void *data)
99 {
100 	return z_impl_z_log_msg_static_create(source, desc, package, data);
101 }
102 #include <syscalls/z_log_msg_static_create_mrsh.c>
103 #endif
104 
z_impl_z_log_msg_runtime_vcreate(uint8_t domain_id,const void * source,uint8_t level,const void * data,size_t dlen,uint32_t package_flags,const char * fmt,va_list ap)105 void z_impl_z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source,
106 				uint8_t level, const void *data, size_t dlen,
107 				uint32_t package_flags, const char *fmt, va_list ap)
108 {
109 	int plen;
110 
111 	if (fmt) {
112 		va_list ap2;
113 
114 		va_copy(ap2, ap);
115 		plen = cbvprintf_package(NULL, Z_LOG_MSG_ALIGN_OFFSET,
116 					 package_flags, fmt, ap2);
117 		__ASSERT_NO_MSG(plen >= 0);
118 		va_end(ap2);
119 	} else {
120 		plen = 0;
121 	}
122 
123 	size_t msg_wlen = Z_LOG_MSG_ALIGNED_WLEN(plen, dlen);
124 	struct log_msg *msg;
125 	uint8_t *pkg;
126 	struct log_msg_desc desc =
127 		Z_LOG_MSG_DESC_INITIALIZER(domain_id, level, plen, dlen);
128 
129 	if (IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) && BACKENDS_IN_USE()) {
130 		msg = z_log_msg_alloc(msg_wlen);
131 		if (IS_ENABLED(CONFIG_LOG_FRONTEND) && msg == NULL) {
132 			pkg = alloca(plen);
133 		} else {
134 			pkg = msg ? msg->data : NULL;
135 		}
136 	} else {
137 		msg = alloca(msg_wlen * sizeof(int));
138 		pkg = msg->data;
139 	}
140 
141 	if (pkg && fmt) {
142 		plen = cbvprintf_package(pkg, (size_t)plen, package_flags, fmt, ap);
143 		__ASSERT_NO_MSG(plen >= 0);
144 	}
145 
146 	if (IS_ENABLED(CONFIG_LOG_FRONTEND)) {
147 		log_frontend_msg(source, desc, pkg, data);
148 	}
149 
150 	if (BACKENDS_IN_USE()) {
151 		z_log_msg_finalize(msg, source, desc, data);
152 	}
153 }
154 
155 #ifdef CONFIG_USERSPACE
z_vrfy_z_log_msg_runtime_vcreate(uint8_t domain_id,const void * source,uint8_t level,const void * data,size_t dlen,uint32_t package_flags,const char * fmt,va_list ap)156 static inline void z_vrfy_z_log_msg_runtime_vcreate(uint8_t domain_id,
157 				const void *source,
158 				uint8_t level, const void *data, size_t dlen,
159 				uint32_t package_flags, const char *fmt, va_list ap)
160 {
161 	return z_impl_z_log_msg_runtime_vcreate(domain_id, source, level, data,
162 						dlen, package_flags, fmt, ap);
163 }
164 #include <syscalls/z_log_msg_runtime_vcreate_mrsh.c>
165 #endif
166