diff --git a/smex/elf.c b/smex/elf.c index bd088716691d..711e061bcdd7 100644 --- a/smex/elf.c +++ b/smex/elf.c @@ -17,7 +17,7 @@ static int elf_read_sections(struct elf_module *module, bool verbose) { Elf32_Ehdr *hdr = &module->hdr; - Elf32_Shdr *section = module->section; + Elf32_Shdr *section; size_t count; int i, ret; uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); @@ -128,7 +128,7 @@ static int elf_read_sections(struct elf_module *module, bool verbose) static int elf_read_programs(struct elf_module *module, bool verbose) { Elf32_Ehdr *hdr = &module->hdr; - Elf32_Phdr *prg = module->prg; + Elf32_Phdr *prg; size_t count; int i, ret; @@ -408,10 +408,17 @@ int elf_find_section(const struct elf_module *module, const char *name) ret = -errno; goto out; } + buffer[section->size - 1] = '\0'; /* find section with name */ for (i = 0; i < hdr->shnum; i++) { s = &module->section[i]; + if (s->name >= section->size) { + fprintf(stderr, "error: invalid section name string index %d\n", s->name); + ret = -EINVAL; + goto out; + } + if (!strcmp(name, buffer + s->name)) { ret = i; goto out; @@ -431,8 +438,8 @@ int elf_read_section(const struct elf_module *module, const char *section_name, const Elf32_Shdr **dst_section, void **dst_buff) { const Elf32_Shdr *section; - int section_index = -1; - int read; + int section_index; + int ret; section_index = elf_find_section(module, section_name); if (section_index < 0) { @@ -451,17 +458,25 @@ int elf_read_section(const struct elf_module *module, const char *section_name, return -ENOMEM; /* fill buffer with section content */ - fseek(module->fd, section->off, SEEK_SET); - read = fread(*dst_buff, 1, section->size, module->fd); - if (read != section->size) { - fprintf(stderr, - "error: can't read %s section %d\n", section_name, - -errno); - free(*dst_buff); - return -errno; + ret = fseek(module->fd, section->off, SEEK_SET); + if (ret) { + fprintf(stderr, "error: can't seek to %s section %d\n", section_name, -errno); + ret = -errno; + goto error; + } + + ret = fread(*dst_buff, 1, section->size, module->fd); + if (ret != section->size) { + fprintf(stderr, "error: can't read %s section %d\n", section_name, -errno); + ret = -errno; + goto error; } return section->size; + +error: + free(*dst_buff); + return ret; } int elf_read_module(struct elf_module *module, const char *name, bool verbose) diff --git a/tools/logger/CMakeLists.txt b/tools/logger/CMakeLists.txt index d84c92ce0cc5..57637706c5d6 100644 --- a/tools/logger/CMakeLists.txt +++ b/tools/logger/CMakeLists.txt @@ -1,5 +1,13 @@ # SPDX-License-Identifier: BSD-3-Clause +# https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How-To-Write-Platform-Checks +INCLUDE (CheckIncludeFiles) +CHECK_INCLUDE_FILES(sys/inotify.h HAS_INOTIFY) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + add_executable(sof-logger logger.c convert.c diff --git a/tools/logger/config.h.in b/tools/logger/config.h.in new file mode 100644 index 000000000000..fecbafbd274c --- /dev/null +++ b/tools/logger/config.h.in @@ -0,0 +1 @@ +#cmakedefine01 HAS_INOTIFY diff --git a/tools/logger/convert.c b/tools/logger/convert.c index 569f81579f52..f8488d70e2d8 100644 --- a/tools/logger/convert.c +++ b/tools/logger/convert.c @@ -60,13 +60,11 @@ struct proc_ldc_entry { uintptr_t params[TRACE_MAX_PARAMS_COUNT]; }; -static const char *BAD_PTR_STR = ""; - +#define BAD_PTR_STR "" #define UUID_LOWER "%s%s%s<%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%s%s%s" #define UUID_UPPER "%s%s%s<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>%s%s%s" -/* pointer to config for global context */ -struct convert_config *global_config; +static const char *missing = ""; static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_address); @@ -131,6 +129,10 @@ static const char *format_uid(uint32_t uid_ptr, int use_colors, bool be, bool up if (uid_ptr < uids_dict->base_address || uid_ptr >= uids_dict->base_address + uids_dict->data_length) { str = calloc(1, strlen(BAD_PTR_STR) + 1 + 6); + if (!str) { + log_err("can't allocate memory\n"); + exit(EXIT_FAILURE); + } sprintf(str, BAD_PTR_STR, uid_ptr); } else { uid_entry = get_uuid_entry(uid_ptr); @@ -248,6 +250,8 @@ static void process_params(struct proc_ldc_entry *pe, /* check for string printing, because it leads to logger crash */ log_err("String printing is not supported\n"); pe->params[i] = (uintptr_t)log_asprintf("", raw_param); + if (!pe->params[i]) + abort(); pe->subst_mask |= 1 << i; ++i; p += 2; @@ -256,6 +260,8 @@ static void process_params(struct proc_ldc_entry *pe, /* substitute UUID entry address with formatted string pointer from heap */ pe->params[i] = (uintptr_t)asprintf_uuid(p, raw_param, use_colors, &uuid_fmt_len); + if (!pe->params[i]) + abort(); pe->subst_mask |= 1 << i; ++i; /* replace uuid formatter with %s */ @@ -267,7 +273,12 @@ static void process_params(struct proc_ldc_entry *pe, /* %pQ format specifier */ /* substitute log entry address with formatted entry text */ pe->params[i] = (uintptr_t)asprintf_entry_text(raw_param); - pe->subst_mask |= 1 << i; + + if (pe->params[i]) + pe->subst_mask |= 1 << i; + else + pe->params[i] = (uintptr_t)missing; + ++i; /* replace entry formatter with %s */ @@ -313,7 +324,7 @@ static unsigned int timestamp_width(unsigned int precision) * gcc 9.3, this avoids a very long precision causing snprintf() * to truncate time_fmt */ - assert(precision >= 0 && precision < 20); + assert(precision < 20); /* * 12 digits for units is enough for 1M seconds = 11 days which * should be enough for most test runs. @@ -327,7 +338,6 @@ static inline void print_table_header(void) { FILE *out_fd = global_config->out_fd; int hide_location = global_config->hide_location; - char time_fmt[32]; char date_string[64]; const time_t epoc_secs = time(NULL); @@ -337,16 +347,14 @@ static inline void print_table_header(void) if (gettime_ret) { log_err("clock_gettime() failed: %s\n", - strerror(gettime_ret)); + strerror(errno)); exit(1); } if (global_config->time_precision >= 0) { - const unsigned int ts_width = - timestamp_width(global_config->time_precision); - snprintf(time_fmt, sizeof(time_fmt), "%%-%ds(us)%%%ds ", - ts_width, ts_width); - fprintf(out_fd, time_fmt, " TIMESTAMP", "DELTA"); + const unsigned int ts_width = timestamp_width(global_config->time_precision); + + fprintf(out_fd, "%*s(us)%*s ", -ts_width, " TIMESTAMP", ts_width, "DELTA"); } fprintf(out_fd, "%2s %-18s ", "C#", "COMPONENT"); @@ -355,11 +363,14 @@ static inline void print_table_header(void) fprintf(out_fd, "%s", "CONTENT"); if (global_config->time_precision >= 0) { + struct tm *ltime = localtime(&epoc_secs); + /* e.g.: ktime=4263.487s @ 2021-04-27 14:21:13 -0700 PDT */ fprintf(out_fd, "\tktime=%lu.%03lus", ktime.tv_sec, ktime.tv_nsec / 1000000); - if (strftime(date_string, sizeof(date_string), - "%F %X %z %Z", localtime(&epoc_secs))) + + if (ltime && strftime(date_string, sizeof(date_string), + "%F %X %z %Z", ltime)) fprintf(out_fd, " @ %s", date_string); } @@ -461,7 +472,6 @@ static void print_entry_params(const struct log_entry_header *dma_log, char ids[TRACE_MAX_IDS_STR]; float dt = to_usecs(dma_log->timestamp - last_timestamp); struct proc_ldc_entry proc_entry; - static char time_fmt[64]; int ret; if (raw_output) @@ -502,13 +512,7 @@ static void print_entry_params(const struct log_entry_header *dma_log, ids[0] = '\0'; if (raw_output) { /* "raw" means script-friendly (not all hex) */ - const char *entry_fmt = "%s%u %u %s%s%s "; - - if (time_precision >= 0) - snprintf(time_fmt, sizeof(time_fmt), "%%.%df %%.%df ", - time_precision, time_precision); - - fprintf(out_fd, entry_fmt, + fprintf(out_fd, "%s%u %u %s%s%s ", entry->header.level == use_colors ? (LOG_LEVEL_CRITICAL ? KRED : KNRM) : "", dma_log->core_id, @@ -516,9 +520,12 @@ static void print_entry_params(const struct log_entry_header *dma_log, get_component_name(entry->header.component_class, dma_log->uid), raw_output && strlen(ids) ? "-" : "", ids); + if (time_precision >= 0) - fprintf(out_fd, time_fmt, - to_usecs(dma_log->timestamp - timestamp_origin), dt); + fprintf(out_fd, "%.*f %.*f ", + time_precision, to_usecs(dma_log->timestamp - timestamp_origin), + time_precision, dt); + if (!hide_location) fprintf(out_fd, "(%s:%u) ", format_file_name(entry->file_name, raw_output), @@ -527,13 +534,11 @@ static void print_entry_params(const struct log_entry_header *dma_log, if (time_precision >= 0) { const unsigned int ts_width = timestamp_width(time_precision); - snprintf(time_fmt, sizeof(time_fmt), - "%%s[%%%d.%df] (%%%d.%df)%%s ", - ts_width, time_precision, ts_width, time_precision); - - fprintf(out_fd, time_fmt, + fprintf(out_fd, "%s[%*.*f] (%*.*f)%s ", use_colors ? KGRN : "", - to_usecs(dma_log->timestamp - timestamp_origin), dt, + ts_width, time_precision, + to_usecs(dma_log->timestamp - timestamp_origin), + ts_width, time_precision, dt, use_colors ? KNRM : ""); } @@ -609,7 +614,13 @@ static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_ entry->params = NULL; /* set file position to beginning of processed entry */ - fseek(global_config->ldc_fd, entry_offset, SEEK_SET); + ret = fseek(global_config->ldc_fd, entry_offset, SEEK_SET); + if (ret) { + log_err("Failed to seek to entry header for offset 0x%x in dictionary.\n", + entry_offset); + ret = -errno; + goto out; + } /* fetching elf header params */ ret = fread(&entry->header, sizeof(entry->header), 1, global_config->ldc_fd); @@ -625,7 +636,7 @@ static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_ ret = -EINVAL; goto out; } - entry->file_name = (char *)malloc(entry->header.file_name_len); + entry->file_name = (char *)malloc(entry->header.file_name_len + 1); if (!entry->file_name) { log_err("can't allocate %d byte for entry.file_name\n", @@ -636,6 +647,8 @@ static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_ ret = fread(entry->file_name, sizeof(char), entry->header.file_name_len, global_config->ldc_fd); + entry->file_name[entry->header.file_name_len] = '\0'; + if (ret != entry->header.file_name_len) { log_err("Failed to read source filename for offset 0x%x in dictionary.\n", entry_offset); @@ -649,7 +662,7 @@ static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_ ret = -EINVAL; goto out; } - entry->text = (char *)malloc(entry->header.text_len); + entry->text = (char *)malloc(entry->header.text_len + 1); if (!entry->text) { log_err("can't allocate %d byte for entry.text\n", entry->header.text_len); ret = -ENOMEM; @@ -662,6 +675,7 @@ static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_ ret = -1; goto out; } + entry->text[entry->header.text_len] = '\0'; return 0; @@ -900,8 +914,13 @@ static int logger_read(void) /* When the address is not correct, move forward by one DWORD (not * entire struct dma_log) */ - fseek(global_config->in_fd, -(sizeof(dma_log) - sizeof(uint32_t)), + ret = fseek(global_config->in_fd, -(sizeof(dma_log) - sizeof(uint32_t)), SEEK_CUR); + if (ret) { + log_err("fetch_entry() failed on seek, aborting\n"); + ret = -errno; + break; + } skipped_dwords++; continue; @@ -998,7 +1017,7 @@ static int dump_ldc_info(void) if (global_config->version_fd) { struct sof_ipc_fw_version ver; - if (fread(&ver, sizeof(ver), 1, global_config->version_fd)) + if (fread(&ver, sizeof(ver), 1, global_config->version_fd) == 1) fprintf(out_fd, "Loaded FW expects checksum\t0x%08x\n", ver.src_hash); } @@ -1017,7 +1036,7 @@ static int dump_ldc_info(void) while (remaining > 0) { name = format_uid_raw(&uid_ptr[cnt], 0, 0, false, false); uid_addr = get_uuid_key(&uid_ptr[cnt]); - fprintf(out_fd, "\t%p %s\n", (void *)uid_addr, name); + fprintf(out_fd, "\t%p %s\n", (void *)uid_addr, name ? name : missing); if (name) { free(name); @@ -1033,36 +1052,45 @@ static int dump_ldc_info(void) return 0; } -int convert(struct convert_config *config) +int convert(void) { - struct snd_sof_logs_header snd; + struct snd_sof_logs_header * const logs_hdr = malloc(sizeof(*logs_hdr)); struct snd_sof_uids_header uids_hdr; int count, ret = 0; - config->logs_header = &snd; - global_config = config; + /* const pointer initialized at build time */ + if (!global_config) + abort(); + + if (!logs_hdr) + abort(); + + /* just a shorter alias */ + struct convert_config * const config = global_config; - count = fread(&snd, sizeof(snd), 1, config->ldc_fd); + config->logs_header = logs_hdr; + + count = fread(logs_hdr, sizeof(*logs_hdr), 1, config->ldc_fd); if (!count) { log_err("Error while reading %s.\n", config->ldc_file); return -ferror(config->ldc_fd); } - if (strncmp((char *) snd.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE)) { + if (strncmp((char *)logs_hdr->sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE)) { log_err("Invalid ldc file signature.\n"); return -EINVAL; } if (global_config->version_fw && /* -n option */ !global_config->dump_ldc) { - ret = verify_ldc_checksum(global_config->logs_header->version.src_hash); + ret = verify_ldc_checksum(logs_hdr->version.src_hash); if (ret) return ret; } /* default logger and ldc_file abi verification */ if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_DBG_VERSION, - snd.version.abi_version)) { + logs_hdr->version.abi_version)) { log_err("abi version in %s file does not coincide with abi version used by logger.\n", config->ldc_file); log_err("logger ABI Version is %d:%d:%d\n", @@ -1070,14 +1098,19 @@ int convert(struct convert_config *config) SOF_ABI_VERSION_MINOR(SOF_ABI_DBG_VERSION), SOF_ABI_VERSION_PATCH(SOF_ABI_DBG_VERSION)); log_err("ldc_file ABI Version is %d:%d:%d\n", - SOF_ABI_VERSION_MAJOR(snd.version.abi_version), - SOF_ABI_VERSION_MINOR(snd.version.abi_version), - SOF_ABI_VERSION_PATCH(snd.version.abi_version)); + SOF_ABI_VERSION_MAJOR(logs_hdr->version.abi_version), + SOF_ABI_VERSION_MINOR(logs_hdr->version.abi_version), + SOF_ABI_VERSION_PATCH(logs_hdr->version.abi_version)); return -EINVAL; } /* read uuid section header */ - fseek(config->ldc_fd, snd.data_offset + snd.data_length, SEEK_SET); + ret = fseek(config->ldc_fd, logs_hdr->data_offset + logs_hdr->data_length, SEEK_SET); + if (ret) { + log_err("Error while seeking to uuids header from %s.\n", config->ldc_file); + return -errno; + } + count = fread(&uids_hdr, sizeof(uids_hdr), 1, config->ldc_fd); if (!count) { log_err("Error while reading uuids header from %s.\n", config->ldc_file); diff --git a/tools/logger/convert.h b/tools/logger/convert.h index 607e5e59e049..dcf8d0db06b7 100644 --- a/tools/logger/convert.h +++ b/tools/logger/convert.h @@ -47,4 +47,8 @@ struct convert_config { }; uint32_t get_uuid_key(const struct sof_uuid_entry *entry); -int convert(struct convert_config *config); + +/* pointer to config for global context */ +extern struct convert_config * const global_config; + +int convert(void); diff --git a/tools/logger/filter.c b/tools/logger/filter.c index b70af55f156b..80b5f72345fd 100644 --- a/tools/logger/filter.c +++ b/tools/logger/filter.c @@ -22,8 +22,6 @@ #define COMPONENTS_SEPARATOR ',' #define COMPONENT_NAME_SCAN_STRING_LENGTH 32 -extern struct convert_config *global_config; - /** map between log level given by user and enum value */ static const struct { const char name[16]; diff --git a/tools/logger/logger.c b/tools/logger/logger.c index 543e8e85a0c8..b6c2b26bd629 100644 --- a/tools/logger/logger.c +++ b/tools/logger/logger.c @@ -5,6 +5,7 @@ // Author: Bartosz Kokoszko // Artur Kloniecki +#include #include #include #include @@ -15,6 +16,18 @@ #include #include #include + +#include +#include + +#include "config.h" + +#if HAS_INOTIFY +#include +#include +#include +#endif + #include "convert.h" #include "misc.h" @@ -91,8 +104,8 @@ static int snapshot(const char *name) for (i = 0; i < ARRAY_SIZE(debugfs); i++) { - sprintf(pinname, "%s/%s", path, debugfs[i]); - sprintf(poutname, "%s.%s.txt", name, debugfs[i]); + snprintf(pinname, sizeof(pinname), "%s/%s", path, debugfs[i]); + snprintf(poutname, sizeof(poutname), "%s.%s.txt", name, debugfs[i]); /* open debugfs for reading */ in_fd = fopen(pinname, "rb"); @@ -119,9 +132,14 @@ static int snapshot(const char *name) if (count != 4) break; - sprintf(buffer, "0x%6.6x: 0x%8.8x\n", addr, val); + snprintf(buffer, sizeof(buffer), "0x%6.6x: 0x%8.8x\n", addr, val); - count = fwrite(buffer, 1, strlen(buffer), out_fd); + i = strlen(buffer); + count = fwrite(buffer, 1, i, out_fd); + if (count != i) { + fprintf(stderr, "error: an error occurred during write to %s: %s\n", + poutname, strerror(errno)); + } addr += 4; } @@ -151,7 +169,12 @@ static int configure_uart(const char *file, unsigned int baud) tio.c_cc[VMIN] = 1; ret = tcsetattr(fd, TCSANOW, &tio); - return ret < 0 ? -errno : fd; + if (ret < 0) { + close(fd); + return -errno; + } + + return fd; } /* Concantenate `config->filter_config` with `input` + `\n` */ @@ -170,6 +193,108 @@ static int append_filter_config(struct convert_config *config, const char *input return 0; } +#if !HAS_INOTIFY +static void *wait_open(const char *watched_dir, const char *expected_file) +{ + assert(HAS_INOTIFY); /* Should never be called */ +} +#else +/* + * This 5 minutes timeout is for "backward compatible safety" in case + * any user/script of an earlier, pre-inotify version of sof-logger + * (accidentally?) _expected_ the tool to quit when the driver was not + * loaded. This expectation was always wrong but an infinite wait is too + * severe of a punishment. This timeout cannot be too small otherwise it + * would defeat the new feature. + */ +#ifndef SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS +#define SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS (5 * 60) +#endif + +/* + * Using inotify, wait up to 5 minutes for 'expected_name' to appear in + * 'watched_dir'. Then return opendir/fopen(expected_name). fopen() and + * opendir() failures are NOT handled; e.g. NULL from fopen() is just + * passed through. + * + * Returns a FILE * or DIR * + */ +static void *wait_open(const char *watched_dir, const char *expected_file) +{ + if (access(watched_dir, R_OK)) { + fprintf(stderr, "error: %s() cannot read %s\n", __func__, watched_dir); + return NULL; + } + + const int iqueue = inotify_init(); + const int dwatch = inotify_add_watch(iqueue, watched_dir, IN_CREATE); + struct stat expected_stat; + void *ret_stream = NULL; + const int fpath_len = strlen(watched_dir) + 1 + strlen(expected_file) + 1; + char * const fpath = malloc(fpath_len); + + if (!fpath) { + fprintf(stderr, "error: can't allocate memory\n"); + exit(EXIT_FAILURE); + } + + snprintf(fpath, fpath_len, "%s/%s", watched_dir, expected_file); + + /* Not racy because the inotify watch was set first. */ + if (!access(fpath, F_OK)) + goto fopenit; + + fprintf(stdout, "%s: waiting in %s/ for %s\n", APP_NAME, watched_dir, expected_file); + fflush(stdout); + + while (1) { + char evlist[1 * sizeof(struct inotify_event)]; + struct pollfd pfd[1] = {{ .fd = iqueue, .events = POLLIN, .revents = 0 }}; + int pret = poll(pfd, sizeof(pfd) / sizeof(struct pollfd), + SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS * 1000); + + if (pret == 0) { + fprintf(stderr, "error: no %s after waiting %d seconds\n", + expected_file, SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS); + goto cleanup; + } + + if (pret < 0 || pfd[0].revents != POLLIN) { + fprintf(stderr, "error: in %s, poll(%s) returned %d, %d\n", + __func__, watched_dir, pret, pfd[0].revents); + goto cleanup; + } + + /* Silence __attribute__((warn_unused_result)) which is + * enabled by some Linux distros even when broken in gcc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 + */ + (void)!read(iqueue, evlist, sizeof(evlist)); + + if (!access(fpath, F_OK)) + goto fopenit; + } + +fopenit: + if (stat(fpath, &expected_stat)) + goto cleanup; + + if ((expected_stat.st_mode & S_IFMT) == S_IFDIR) + ret_stream = opendir(fpath); + else + ret_stream = fopen(fpath, "rb"); + +cleanup: + free(fpath); + inotify_rm_watch(iqueue, dwatch); + + return ret_stream; +} +#endif // HAS_INOTIFY + +static struct convert_config _global_config; +struct convert_config * const global_config = &_global_config; + int main(int argc, char *argv[]) { static const char optstring[] = "ho:i:l:ps:c:u:tv:rd:Le:f:gF:n"; @@ -249,7 +374,8 @@ int main(int argc, char *argv[]) if (i < 0 || 1 < i) { fprintf(stderr, "%s: invalid option: -e %s\n", APP_NAME, optarg); - return -EINVAL; + ret = -EINVAL; + goto out; } config.relative_timestamps = i; break; @@ -258,7 +384,8 @@ int main(int argc, char *argv[]) config.time_precision = atoi(optarg); if (config.time_precision < 0) { usage(); - return -EINVAL; + ret = -EINVAL; + goto out; } break; case 'g': @@ -288,8 +415,10 @@ int main(int argc, char *argv[]) usage(); } - if (snapshot_file) - return baud ? EINVAL : -snapshot(snapshot_file); + if (snapshot_file) { + ret = baud ? EINVAL : -snapshot(snapshot_file); + goto out; + } if (!config.ldc_file) { fprintf(stderr, "error: Missing ldc file\n"); @@ -304,17 +433,6 @@ int main(int argc, char *argv[]) goto out; } - if (config.version_fw) { - config.version_fd = fopen(config.version_file, "rb"); - if (!config.version_fd && !config.dump_ldc) { - ret = errno; - fprintf(stderr, - "error: Unable to open version file %s: %s\n", - config.version_file, strerror(ret)); - goto out; - } - } - if (config.out_file) { config.out_fd = fopen(config.out_file, "w"); if (!config.out_fd) { @@ -339,6 +457,11 @@ int main(int argc, char *argv[]) if (!config.in_file && !config.dump_ldc) config.in_file = "/sys/kernel/debug/sof/etrace"; + if (!config.in_file && baud) { + fprintf(stderr, "error: No UART device specified\n"); + usage(); + } + if (config.input_std) { config.in_fd = stdin; } else if (baud) { @@ -348,7 +471,27 @@ int main(int argc, char *argv[]) goto out; } } else if (config.in_file) { - config.in_fd = fopen(config.in_file, "rb"); + static const char sys_debug[] = "/sys/kernel/debug"; + static const char sys_debug_sof[] = "/sys/kernel/debug/sof"; + /* In the future we could add an option to force waiting + * for _any_ input file, not just for /sys/kernel/debug/sof/[e]trace + */ + config.in_fd = NULL; + if (!HAS_INOTIFY || + strncmp(config.in_file, sys_debug, strlen(sys_debug))) { + config.in_fd = fopen(config.in_file, "rb"); + } else { // both inotify and /sys/kernel/debug/ + DIR *dbg_sof = (DIR *)wait_open(sys_debug, "sof"); + + if (dbg_sof) { + closedir(dbg_sof); + config.in_fd = + (FILE *)wait_open(sys_debug_sof, + config.in_file + + strlen(sys_debug_sof) + 1); + } + } + if (!config.in_fd) { ret = errno; fprintf(stderr, @@ -360,7 +503,19 @@ int main(int argc, char *argv[]) if (isatty(fileno(config.out_fd)) != 1) config.use_colors = 0; - ret = -convert(&config); + if (config.version_fw) { + config.version_fd = fopen(config.version_file, "rb"); + if (!config.version_fd && !config.dump_ldc) { + ret = errno; + fprintf(stderr, + "error: Unable to open version file %s: %s\n", + config.version_file, strerror(ret)); + goto out; + } + } + + _global_config = config; + ret = -convert(); out: /* free memory */ diff --git a/tools/logger/misc.c b/tools/logger/misc.c index 37ca30adb9c1..20e5db9f95b8 100644 --- a/tools/logger/misc.c +++ b/tools/logger/misc.c @@ -41,8 +41,6 @@ char *log_asprintf(const char *format, ...) return result; } -extern struct convert_config *global_config; - /** Prints 1. once to stderr. 2. a second time to the global out_fd if * out_fd is neither stderr nor stdout (because the -o option was used). */