blob: 88ee93ad3e9fd1b02e02319a03cc0a8df24f2081 [file] [log] [blame]
Sean Nelson74aa7722010-01-07 20:21:58 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Sean Nelson <audiohacked@gmail.com>
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +00005 * Copyright (C) 2011 Carl-Daniel Hailfinger
Sean Nelson74aa7722010-01-07 20:21:58 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Sean Nelson74aa7722010-01-07 20:21:58 +000016 */
17
18#include <stdio.h>
19#include <stdarg.h>
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000020#include <string.h>
21#include <errno.h>
Nico Huberb82aadc2023-02-11 18:27:30 +010022
Sean Nelson74aa7722010-01-07 20:21:58 +000023#include "flash.h"
Nico Huberb82aadc2023-02-11 18:27:30 +010024#include "cli.h"
Sean Nelson74aa7722010-01-07 20:21:58 +000025
Nico Huberc3b02dc2023-08-12 01:13:45 +020026enum flashprog_log_level verbose_screen = FLASHPROG_MSG_INFO;
27enum flashprog_log_level verbose_logfile = FLASHPROG_MSG_DEBUG2;
Stefan Tauner9b32de92014-08-08 23:52:33 +000028
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000029static FILE *logfile = NULL;
30
31int close_logfile(void)
32{
33 if (!logfile)
34 return 0;
35 /* No need to call fflush() explicitly, fclose() already does that. */
36 if (fclose(logfile)) {
37 /* fclose returned an error. Stop writing to be safe. */
38 logfile = NULL;
Stefan Taunerc2eec2c2014-05-03 21:33:01 +000039 msg_gerr("Closing the log file returned error %s\n", strerror(errno));
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000040 return 1;
41 }
42 logfile = NULL;
43 return 0;
44}
45
46int open_logfile(const char * const filename)
47{
48 if (!filename) {
Stefan Tauner0554ca52013-07-25 22:54:25 +000049 msg_gerr("No logfile name specified.\n");
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000050 return 1;
51 }
52 if ((logfile = fopen(filename, "w")) == NULL) {
Stefan Tauner363fd7e2013-04-07 13:08:30 +000053 msg_gerr("Error: opening log file \"%s\" failed: %s\n", filename, strerror(errno));
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000054 return 1;
55 }
56 return 0;
57}
58
59void start_logging(void)
60{
Nico Huberc3b02dc2023-08-12 01:13:45 +020061 enum flashprog_log_level oldverbose_screen = verbose_screen;
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000062
63 /* Shut up the console. */
Nico Huberc3b02dc2023-08-12 01:13:45 +020064 verbose_screen = FLASHPROG_MSG_ERROR;
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000065 print_version();
66 verbose_screen = oldverbose_screen;
67}
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +000068
Richard Hughes842d6782021-01-15 09:48:12 +000069static const char *flashprog_progress_stage_to_string(enum flashprog_progress_stage stage)
70{
71 if (stage == FLASHPROG_PROGRESS_READ)
Nico Huber806509b2023-04-23 00:02:57 +010072 return "Reading";
Richard Hughes842d6782021-01-15 09:48:12 +000073 if (stage == FLASHPROG_PROGRESS_WRITE)
Nico Huber806509b2023-04-23 00:02:57 +010074 return "Writing";
Richard Hughes842d6782021-01-15 09:48:12 +000075 if (stage == FLASHPROG_PROGRESS_ERASE)
Nico Huber806509b2023-04-23 00:02:57 +010076 return "Erasing";
77 return "Progress";
78}
79
80static void print_progress_bar(enum flashprog_progress_stage stage, unsigned int pc)
81{
82 char progress_line[73], *bar;
83 unsigned int i;
84
85 const int bar_start = snprintf(progress_line, sizeof(progress_line), "%s... [",
86 flashprog_progress_stage_to_string(stage));
87
88 for (bar = progress_line + bar_start, i = 0; i < pc; i += 2)
89 *bar++ = '=';
90 if (i < 100)
91 *bar++ = '>', i += 2;
92 for (; i < 100; i += 2)
93 *bar++ = ' ';
94
95 snprintf(bar, sizeof(progress_line) - (bar - progress_line), "] %3u%% ", pc);
96
97 printf("\r%s", progress_line);
Richard Hughes842d6782021-01-15 09:48:12 +000098}
99
100void flashprog_progress_cb(enum flashprog_progress_stage stage, size_t current, size_t total, void *user_data)
101{
102 static enum flashprog_progress_stage last_stage = (enum flashprog_progress_stage)-1;
103 static unsigned int last_pc = (unsigned int)-1;
104
105 const unsigned int pc = total ? (current * 100ull) / total : 100;
106
107 if (last_stage == stage && last_pc == pc)
108 return;
109
Nico Huber806509b2023-04-23 00:02:57 +0100110 if (last_stage != stage || pc == 0)
111 printf("\n");
112
113 print_progress_bar(stage, pc);
Richard Hughes842d6782021-01-15 09:48:12 +0000114 last_stage = stage;
115 last_pc = pc;
116}
117
Carl-Daniel Hailfinger901a3ba2012-05-14 22:54:58 +0000118/* Please note that level is the verbosity, not the importance of the message. */
Nico Huberc3b02dc2023-08-12 01:13:45 +0200119int flashprog_print_cb(enum flashprog_log_level level, const char *fmt, va_list ap)
Sean Nelson74aa7722010-01-07 20:21:58 +0000120{
Carl-Daniel Hailfinger901a3ba2012-05-14 22:54:58 +0000121 int ret = 0;
122 FILE *output_type = stdout;
Uwe Hermann43959702010-03-13 17:28:29 +0000123
Nico Huber18781102012-12-10 13:34:12 +0000124 va_list logfile_args;
125 va_copy(logfile_args, ap);
126
Nico Huberc3b02dc2023-08-12 01:13:45 +0200127 if (level < FLASHPROG_MSG_INFO)
Sean Nelson74aa7722010-01-07 20:21:58 +0000128 output_type = stderr;
Uwe Hermann43959702010-03-13 17:28:29 +0000129
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +0000130 if (level <= verbose_screen) {
Carl-Daniel Hailfinger901a3ba2012-05-14 22:54:58 +0000131 ret = vfprintf(output_type, fmt, ap);
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000132 /* msg_*spew often happens inside chip accessors in possibly
133 * time-critical operations. Don't slow them down by flushing. */
Nico Huberc3b02dc2023-08-12 01:13:45 +0200134 if (level != FLASHPROG_MSG_SPEW)
Carl-Daniel Hailfinger901a3ba2012-05-14 22:54:58 +0000135 fflush(output_type);
136 }
Thomas Heijligene2767652022-04-07 17:48:53 +0200137
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +0000138 if ((level <= verbose_logfile) && logfile) {
Nico Huber18781102012-12-10 13:34:12 +0000139 ret = vfprintf(logfile, fmt, logfile_args);
Nico Huberc3b02dc2023-08-12 01:13:45 +0200140 if (level != FLASHPROG_MSG_SPEW)
Carl-Daniel Hailfinger1c155482012-06-06 09:17:06 +0000141 fflush(logfile);
142 }
Thomas Heijligene2767652022-04-07 17:48:53 +0200143
Nico Huber18781102012-12-10 13:34:12 +0000144 va_end(logfile_args);
Sean Nelson74aa7722010-01-07 20:21:58 +0000145 return ret;
146}