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