| /* |
| * Copyright (c) 2020 Nordic Semiconductor |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #include <zephyr/kernel.h> |
| #include <zephyr/syscall_handler.h> |
| #include <zephyr/logging/log_internal.h> |
| #include <zephyr/logging/log_ctrl.h> |
| #include <zephyr/logging/log_frontend.h> |
| #include <zephyr/logging/log_backend.h> |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_DECLARE(log); |
| |
| BUILD_ASSERT(sizeof(struct log_msg_desc) == sizeof(uint32_t), |
| "Descriptor must fit in 32 bits"); |
| |
| /* Returns true if any backend is in use. */ |
| #define BACKENDS_IN_USE() \ |
| !(IS_ENABLED(CONFIG_LOG_FRONTEND) && \ |
| (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY) || log_backend_count_get() == 0)) |
| |
| void z_log_msg_finalize(struct log_msg *msg, const void *source, |
| const struct log_msg_desc desc, const void *data) |
| { |
| if (!msg) { |
| z_log_dropped(false); |
| |
| return; |
| } |
| |
| if (data) { |
| uint8_t *d = msg->data + desc.package_len; |
| |
| memcpy(d, data, desc.data_len); |
| } |
| |
| msg->hdr.desc = desc; |
| msg->hdr.source = source; |
| z_log_msg_commit(msg); |
| } |
| |
| void z_impl_z_log_msg_static_create(const void *source, |
| const struct log_msg_desc desc, |
| uint8_t *package, const void *data) |
| { |
| if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { |
| log_frontend_msg(source, desc, package, data); |
| } |
| |
| if (!BACKENDS_IN_USE()) { |
| return; |
| } |
| |
| struct log_msg_desc out_desc = desc; |
| int inlen = desc.package_len; |
| struct log_msg *msg; |
| |
| if (inlen > 0) { |
| uint32_t flags = CBPRINTF_PACKAGE_CONVERT_RW_STR | |
| CBPRINTF_PACKAGE_CONVERT_PTR_CHECK; |
| uint16_t strl[4]; |
| int len; |
| |
| len = cbprintf_package_copy(package, inlen, |
| NULL, 0, flags, |
| strl, ARRAY_SIZE(strl)); |
| |
| if (len > Z_LOG_MSG_MAX_PACKAGE) { |
| struct cbprintf_package_hdr_ext *pkg = |
| (struct cbprintf_package_hdr_ext *)package; |
| |
| LOG_WRN("Message (\"%s\") dropped because it exceeds size limitation (%u)", |
| pkg->fmt, (uint32_t)Z_LOG_MSG_MAX_PACKAGE); |
| return; |
| } |
| /* Update package length with calculated value (which may be extended |
| * when strings are copied into the package. |
| */ |
| out_desc.package_len = len; |
| msg = z_log_msg_alloc(log_msg_get_total_wlen(out_desc)); |
| if (msg) { |
| len = cbprintf_package_copy(package, inlen, |
| msg->data, out_desc.package_len, |
| flags, strl, ARRAY_SIZE(strl)); |
| __ASSERT_NO_MSG(len >= 0); |
| } |
| } else { |
| msg = z_log_msg_alloc(log_msg_get_total_wlen(out_desc)); |
| } |
| |
| z_log_msg_finalize(msg, source, out_desc, data); |
| } |
| |
| #ifdef CONFIG_USERSPACE |
| static inline void z_vrfy_z_log_msg_static_create(const void *source, |
| const struct log_msg_desc desc, |
| uint8_t *package, const void *data) |
| { |
| return z_impl_z_log_msg_static_create(source, desc, package, data); |
| } |
| #include <syscalls/z_log_msg_static_create_mrsh.c> |
| #endif |
| |
| void 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) |
| { |
| int plen; |
| |
| if (fmt) { |
| va_list ap2; |
| |
| va_copy(ap2, ap); |
| plen = cbvprintf_package(NULL, Z_LOG_MSG_ALIGN_OFFSET, |
| package_flags, fmt, ap2); |
| __ASSERT_NO_MSG(plen >= 0); |
| va_end(ap2); |
| } else { |
| plen = 0; |
| } |
| |
| size_t msg_wlen = Z_LOG_MSG_ALIGNED_WLEN(plen, dlen); |
| struct log_msg *msg; |
| uint8_t *pkg; |
| struct log_msg_desc desc = |
| Z_LOG_MSG_DESC_INITIALIZER(domain_id, level, plen, dlen); |
| |
| if (IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) && BACKENDS_IN_USE()) { |
| msg = z_log_msg_alloc(msg_wlen); |
| if (IS_ENABLED(CONFIG_LOG_FRONTEND) && msg == NULL) { |
| pkg = alloca(plen); |
| } else { |
| pkg = msg ? msg->data : NULL; |
| } |
| } else { |
| msg = alloca(msg_wlen * sizeof(int)); |
| pkg = msg->data; |
| } |
| |
| if (pkg && fmt) { |
| plen = cbvprintf_package(pkg, (size_t)plen, package_flags, fmt, ap); |
| __ASSERT_NO_MSG(plen >= 0); |
| } |
| |
| if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { |
| log_frontend_msg(source, desc, pkg, data); |
| } |
| |
| if (BACKENDS_IN_USE()) { |
| z_log_msg_finalize(msg, source, desc, data); |
| } |
| } |
| |
| #ifdef CONFIG_USERSPACE |
| static inline void 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) |
| { |
| return z_impl_z_log_msg_runtime_vcreate(domain_id, source, level, data, |
| dlen, package_flags, fmt, ap); |
| } |
| #include <syscalls/z_log_msg_runtime_vcreate_mrsh.c> |
| #endif |