1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Sean Nelson <[email protected]>
5 * Copyright (C) 2011 Carl-Daniel Hailfinger
6 *
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.
16 */
17
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <errno.h>
22 #include "flash.h"
23
24 enum flashrom_log_level verbose_screen = FLASHROM_MSG_INFO;
25 enum flashrom_log_level verbose_logfile = FLASHROM_MSG_DEBUG2;
26
27 static FILE *logfile = NULL;
28
close_logfile(void)29 int close_logfile(void)
30 {
31 if (!logfile)
32 return 0;
33 /* No need to call fflush() explicitly, fclose() already does that. */
34 if (fclose(logfile)) {
35 /* fclose returned an error. Stop writing to be safe. */
36 logfile = NULL;
37 msg_gerr("Closing the log file returned error %s\n", strerror(errno));
38 return 1;
39 }
40 logfile = NULL;
41 return 0;
42 }
43
open_logfile(const char * const filename)44 int open_logfile(const char * const filename)
45 {
46 if (!filename) {
47 msg_gerr("No logfile name specified.\n");
48 return 1;
49 }
50 if ((logfile = fopen(filename, "w")) == NULL) {
51 msg_gerr("Error: opening log file \"%s\" failed: %s\n", filename, strerror(errno));
52 return 1;
53 }
54 return 0;
55 }
56
start_logging(void)57 void start_logging(void)
58 {
59 enum flashrom_log_level oldverbose_screen = verbose_screen;
60
61 /* Shut up the console. */
62 verbose_screen = FLASHROM_MSG_ERROR;
63 print_version();
64 verbose_screen = oldverbose_screen;
65 }
66
flashrom_progress_stage_to_string(enum flashrom_progress_stage stage)67 static const char *flashrom_progress_stage_to_string(enum flashrom_progress_stage stage)
68 {
69 if (stage == FLASHROM_PROGRESS_READ)
70 return "READ";
71 if (stage == FLASHROM_PROGRESS_WRITE)
72 return "WRITE";
73 if (stage == FLASHROM_PROGRESS_ERASE)
74 return "ERASE";
75 return "UNKNOWN";
76 }
77
flashrom_progress_cb(struct flashrom_flashctx * flashctx)78 void flashrom_progress_cb(struct flashrom_flashctx *flashctx)
79 {
80 struct flashrom_progress *progress_state = flashctx->progress_state;
81 unsigned int pc = 0;
82 unsigned int *percentages = progress_state->user_data;
83 if (progress_state->current > 0 && progress_state->total > 0)
84 pc = ((unsigned long long) progress_state->current * 10000llu) /
85 ((unsigned long long) progress_state->total * 100llu);
86 if (percentages[progress_state->stage] != pc) {
87 percentages[progress_state->stage] = pc;
88 msg_ginfo("[%s] %u%% complete... ", flashrom_progress_stage_to_string(progress_state->stage), pc);
89 }
90 }
91
92 /* Please note that level is the verbosity, not the importance of the message. */
flashrom_print_cb(enum flashrom_log_level level,const char * fmt,va_list ap)93 int flashrom_print_cb(enum flashrom_log_level level, const char *fmt, va_list ap)
94 {
95 int ret = 0;
96 FILE *output_type = stdout;
97
98 va_list logfile_args;
99 va_copy(logfile_args, ap);
100
101 if (level < FLASHROM_MSG_INFO)
102 output_type = stderr;
103
104 if (level <= verbose_screen) {
105 ret = vfprintf(output_type, fmt, ap);
106 /* msg_*spew often happens inside chip accessors in possibly
107 * time-critical operations. Don't slow them down by flushing. */
108 if (level != FLASHROM_MSG_SPEW)
109 fflush(output_type);
110 }
111
112 if ((level <= verbose_logfile) && logfile) {
113 ret = vfprintf(logfile, fmt, logfile_args);
114 if (level != FLASHROM_MSG_SPEW)
115 fflush(logfile);
116 }
117
118 va_end(logfile_args);
119 return ret;
120 }
121