/* * Copyright (c) 2019 Intel corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include static struct mipi_syst_header log_syst_header; static struct mipi_syst_handle log_syst_handle; #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA) static const char pattern[] = "SYS-T RAW DATA: "; static const char valToHex[] = "0123456789ABCDEF"; static int out_func(int c, void *ctx) { const struct log_output *out_ctx = (const struct log_output *)ctx; out_ctx->buf[out_ctx->control_block->offset] = (uint8_t)c; out_ctx->control_block->offset++; __ASSERT_NO_MSG(out_ctx->control_block->offset <= out_ctx->size); if (out_ctx->control_block->offset == out_ctx->size) { log_output_flush(out_ctx); } return 0; } static void write_raw(struct mipi_syst_handle *systh, const void *p, int n) { int i; uint8_t c; #if defined(MIPI_SYST_BIG_ENDIAN) for (i = n - 1; i >= 0; --i) { #else for (i = 0; i < n; ++i) { #endif c = ((const uint8_t *)p)[i]; out_func(valToHex[c >> 0x4], systh->systh_platform.log_output); out_func(valToHex[c & 0xF], systh->systh_platform.log_output); } } static void write_d8(struct mipi_syst_handle *systh, uint8_t v) { write_raw(systh, &v, sizeof(v)); } static void write_d16(struct mipi_syst_handle *systh, uint16_t v) { write_raw(systh, &v, sizeof(v)); } static void write_d32(struct mipi_syst_handle *systh, uint32_t v) { write_raw(systh, &v, sizeof(v)); } #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO) static void write_d64(struct mipi_syst_handle *systh, uint64_t v) { write_raw(systh, &v, sizeof(v)); } #endif static void write_d32ts(struct mipi_syst_handle *systh, uint32_t v) { for (int i = 0; i < strlen(pattern); i++) { out_func(pattern[i], systh->systh_platform.log_output); } write_raw(systh, &v, sizeof(v)); } static void write_flag(struct mipi_syst_handle *systh) { uint32_t flag = systh->systh_platform.flag; if ((flag & LOG_OUTPUT_FLAG_CRLF_NONE) != 0U) { return; } if ((flag & LOG_OUTPUT_FLAG_CRLF_LFONLY) != 0U) { out_func('\n', systh->systh_platform.log_output); } else { out_func('\r', systh->systh_platform.log_output); out_func('\n', systh->systh_platform.log_output); } } #endif #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) mipi_syst_u64 mipi_syst_get_epoch(void) { return k_uptime_ticks(); } #endif static void update_systh_platform_data(struct mipi_syst_handle *handle, const struct log_output *log_output, uint32_t flag) { #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA) handle->systh_platform.flag = (mipi_syst_u32)flag; handle->systh_platform.log_output = (struct log_output *)log_output; #endif } #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA) /* * Platform specific SyS-T handle initialization hook function * * @param systh pointer to the SyS-T handle structure */ static void platform_handle_init(struct mipi_syst_handle *systh) { #if defined(MIPI_SYST_PCFG_LENGTH_FIELD) MIPI_SYST_ENABLE_HANDLE_LENGTH(systh, 1); #endif #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) MIPI_SYST_ENABLE_HANDLE_TIMESTAMP(systh, 1); #endif } static void platform_handle_release(struct mipi_syst_handle *systh) { ARG_UNUSED(systh); } #endif /* * Platform specific global state initialization hook function * * @param systh pointer to the new SyS-T handle structure * @param platform_data user defined data for the init function. * */ static void mipi_syst_platform_init(struct mipi_syst_header *systh, const void *platform_data) { #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA) systh->systh_inith = platform_handle_init; systh->systh_releaseh = platform_handle_release; #endif #if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA) systh->systh_platform.write_d8 = write_d8; systh->systh_platform.write_d16 = write_d16; systh->systh_platform.write_d32 = write_d32; #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO) systh->systh_platform.write_d64 = write_d64; #endif systh->systh_platform.write_d32ts = write_d32ts; systh->systh_platform.write_flag = write_flag; #endif } /* * 0 MIPI_SYST_SEVERITY_MAX no assigned severity * 1 MIPI_SYST_SEVERITY_FATAL critical error level * 2 MIPI_SYST_SEVERITY_ERROR error message level * 3 MIPI_SYST_SEVERITY_WARNING warning message level * 4 MIPI_SYST_SEVERITY_INFO information message level * 5 MIPI_SYST_SEVERITY_USER1 user defined level 5 * 6 MIPI_SYST_SEVERITY_USER2 user defined level 6 * 7 MIPI_SYST_SEVERITY_DEBUG debug information level */ static uint32_t level_to_syst_severity(uint32_t level) { uint32_t ret; switch (level) { case LOG_LEVEL_NONE: ret = 0U; break; case LOG_LEVEL_ERR: ret = 2U; break; case LOG_LEVEL_WRN: ret = 3U; break; case LOG_LEVEL_INF: ret = 4U; break; case LOG_LEVEL_DBG: ret = 7U; break; default: ret = 7U; break; } return ret; } static void std_print(struct log_msg *msg, const struct log_output *log_output) { const char *str = log_msg_str_get(msg); uint32_t nargs = log_msg_nargs_get(msg); uint32_t *args = alloca(sizeof(uint32_t)*nargs); uint32_t severity = level_to_syst_severity(log_msg_level_get(msg)); for (int i = 0; i < nargs; i++) { args[i] = log_msg_arg_get(msg, i); } switch (log_msg_nargs_get(msg)) { case 0: MIPI_SYST_PRINTF(&log_syst_handle, severity, str); break; case 1: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0]); break; case 2: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1]); break; case 3: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2]); break; case 4: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3]); break; case 5: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4]); break; case 6: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5]); break; case 7: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break; case 8: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break; case 9: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break; case 10: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); break; case 11: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); break; case 12: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); break; case 13: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]); break; case 14: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]); break; case 15: MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]); break; default: /* Unsupported number of arguments. */ __ASSERT_NO_MSG(true); break; } } static void raw_string_print(struct log_msg *msg, const struct log_output *log_output) { char buf[CONFIG_LOG_STRDUP_MAX_STRING + 1]; size_t length = CONFIG_LOG_STRDUP_MAX_STRING; uint32_t severity = level_to_syst_severity(log_msg_level_get(msg)); log_msg_hexdump_data_get(msg, buf, &length, 0); buf[length] = '\0'; MIPI_SYST_PRINTF(&log_syst_handle, severity, buf); } static void hexdump_print(struct log_msg *msg, const struct log_output *log_output) { char buf[CONFIG_LOG_STRDUP_MAX_STRING + 1]; size_t length = CONFIG_LOG_STRDUP_MAX_STRING; uint32_t severity = level_to_syst_severity(log_msg_level_get(msg)); log_msg_hexdump_data_get(msg, buf, &length, 0); MIPI_SYST_WRITE(&log_syst_handle, severity, 0x1A, buf, length); } void log_output_msg_syst_process(const struct log_output *log_output, struct log_msg *msg, uint32_t flag) { uint8_t level = (uint8_t)log_msg_level_get(msg); bool raw_string = (level == LOG_LEVEL_INTERNAL_RAW_STRING); update_systh_platform_data(&log_syst_handle, log_output, flag); if (log_msg_is_std(msg)) { std_print(msg, log_output); } else if (raw_string) { raw_string_print(msg, log_output); } else { hexdump_print(msg, log_output); } } void log_output_string_syst_process(const struct log_output *log_output, struct log_msg_ids src_level, const char *fmt, va_list ap, uint32_t flag) { uint8_t str[CONFIG_LOG_STRDUP_MAX_STRING]; size_t length = CONFIG_LOG_STRDUP_MAX_STRING; uint32_t severity = level_to_syst_severity((uint32_t)src_level.level); length = vsnprintk(str, length, fmt, ap); str[length] = '\0'; update_systh_platform_data(&log_syst_handle, log_output, flag); MIPI_SYST_PRINTF(&log_syst_handle, severity, str); } void log_output_hexdump_syst_process(const struct log_output *log_output, struct log_msg_ids src_level, const uint8_t *data, uint32_t length, uint32_t flag) { uint32_t severity = level_to_syst_severity((uint32_t)src_level.level); update_systh_platform_data(&log_syst_handle, log_output, flag); MIPI_SYST_WRITE(&log_syst_handle, severity, 0x1A, data, length); } static int syst_init(struct device *arg) { ARG_UNUSED(arg); MIPI_SYST_INIT_STATE(&log_syst_header, mipi_syst_platform_init, (void *)0); MIPI_SYST_INIT_HANDLE_STATE(&log_syst_header, &log_syst_handle, NULL); return 0; } SYS_INIT(syst_init, POST_KERNEL, 0);