util/cbmem: Add -2/--2ndtolast option to print second-to-last boot log

On some platforms, runtime firmware crashes write logs to the CBMEM
console. For those, since a crash reboots the system, by the time we
have a chance to run `cbmem` again the boot where the crash happened
will be the one before the "last" (current) boot. So cbmem -1 doesn't
show the interesting part, and cbmem -c potentially shows a lot that is
cumbersome to dig through. This patch introduces a new option cbmem -2
to explicitly show only the boot cycle before the last one.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: I6725698f4c9ae07011cbacf0928544cebb4ad6f8
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57510
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
This commit is contained in:
Julius Werner 2021-09-08 16:10:15 -07:00
parent 2c59a3884d
commit 8202fc42d4
1 changed files with 31 additions and 11 deletions

View File

@ -715,12 +715,18 @@ struct cbmem_console {
#define CBMC_CURSOR_MASK ((1 << 28) - 1) #define CBMC_CURSOR_MASK ((1 << 28) - 1)
#define CBMC_OVERFLOW (1 << 31) #define CBMC_OVERFLOW (1 << 31)
enum console_print_type {
CONSOLE_PRINT_FULL = 0,
CONSOLE_PRINT_LAST,
CONSOLE_PRINT_PREVIOUS,
};
/* dump the cbmem console */ /* dump the cbmem console */
static void dump_console(int one_boot_only) static void dump_console(enum console_print_type type)
{ {
const struct cbmem_console *console_p; const struct cbmem_console *console_p;
char *console_c; char *console_c;
size_t size, cursor; size_t size, cursor, previous;
struct mapping console_mapping; struct mapping console_mapping;
if (console.tag != LB_TAG_CBMEM_CONSOLE) { if (console.tag != LB_TAG_CBMEM_CONSOLE) {
@ -773,12 +779,12 @@ static void dump_console(int one_boot_only)
if (!isprint(console_c[cursor]) && !isspace(console_c[cursor])) if (!isprint(console_c[cursor]) && !isspace(console_c[cursor]))
console_c[cursor] = '?'; console_c[cursor] = '?';
/* We detect the last boot by looking for a bootblock, romstage or /* We detect the reboot cutoff by looking for a bootblock, romstage or
ramstage banner, in that order (to account for platforms without ramstage banner, in that order (to account for platforms without
CONFIG_BOOTBLOCK_CONSOLE and/or CONFIG_EARLY_CONSOLE). Once we find CONFIG_BOOTBLOCK_CONSOLE and/or CONFIG_EARLY_CONSOLE). Once we find
a banner, store the last match for that stage in cursor and stop. */ a banner, store the last two matches for that stage and stop. */
cursor = 0; cursor = previous = 0;
if (one_boot_only) { if (type != CONSOLE_PRINT_FULL) {
#define BANNER_REGEX(stage) \ #define BANNER_REGEX(stage) \
"\n\ncoreboot-[^\n]* " stage " starting.*\\.\\.\\.\n" "\n\ncoreboot-[^\n]* " stage " starting.*\\.\\.\\.\n"
#define OVERFLOW_REGEX(stage) "\n\\*\\*\\* Pre-CBMEM " stage " console overflow" #define OVERFLOW_REGEX(stage) "\n\\*\\*\\* Pre-CBMEM " stage " console overflow"
@ -796,12 +802,19 @@ static void dump_console(int one_boot_only)
assert(!regcomp(&re, regex[i], 0)); assert(!regcomp(&re, regex[i], 0));
/* Keep looking for matches so we find the last one. */ /* Keep looking for matches so we find the last one. */
while (!regexec(&re, console_c + cursor, 1, &match, 0)) while (!regexec(&re, console_c + cursor, 1, &match, 0)) {
previous = cursor;
cursor += match.rm_so + 1; cursor += match.rm_so + 1;
}
regfree(&re); regfree(&re);
} }
} }
if (type == CONSOLE_PRINT_PREVIOUS) {
console_c[cursor] = '\0';
cursor = previous;
}
puts(console_c + cursor); puts(console_c + cursor);
free(console_c); free(console_c);
unmap_memory(&console_mapping); unmap_memory(&console_mapping);
@ -1087,6 +1100,7 @@ static void print_usage(const char *name, int exit_code)
printf("\n" printf("\n"
" -c | --console: print cbmem console\n" " -c | --console: print cbmem console\n"
" -1 | --oneboot: print cbmem console for last boot only\n" " -1 | --oneboot: print cbmem console for last boot only\n"
" -2 | --2ndtolast: print cbmem console for the boot that came before the last one only\n"
" -C | --coverage: dump coverage information\n" " -C | --coverage: dump coverage information\n"
" -l | --list: print cbmem table of contents\n" " -l | --list: print cbmem table of contents\n"
" -x | --hexdump: print hexdump of cbmem area\n" " -x | --hexdump: print hexdump of cbmem area\n"
@ -1227,13 +1241,14 @@ int main(int argc, char** argv)
int print_timestamps = 0; int print_timestamps = 0;
int print_tcpa_log = 0; int print_tcpa_log = 0;
int machine_readable_timestamps = 0; int machine_readable_timestamps = 0;
int one_boot_only = 0; enum console_print_type console_type = CONSOLE_PRINT_FULL;
unsigned int rawdump_id = 0; unsigned int rawdump_id = 0;
int opt, option_index = 0; int opt, option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
{"console", 0, 0, 'c'}, {"console", 0, 0, 'c'},
{"oneboot", 0, 0, '1'}, {"oneboot", 0, 0, '1'},
{"2ndtolast", 0, 0, '2'},
{"coverage", 0, 0, 'C'}, {"coverage", 0, 0, 'C'},
{"list", 0, 0, 'l'}, {"list", 0, 0, 'l'},
{"tcpa-log", 0, 0, 'L'}, {"tcpa-log", 0, 0, 'L'},
@ -1246,7 +1261,7 @@ int main(int argc, char** argv)
{"help", 0, 0, 'h'}, {"help", 0, 0, 'h'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
while ((opt = getopt_long(argc, argv, "c1CltTLxVvh?r:", while ((opt = getopt_long(argc, argv, "c12CltTLxVvh?r:",
long_options, &option_index)) != EOF) { long_options, &option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'c': case 'c':
@ -1255,7 +1270,12 @@ int main(int argc, char** argv)
break; break;
case '1': case '1':
print_console = 1; print_console = 1;
one_boot_only = 1; console_type = CONSOLE_PRINT_LAST;
print_defaults = 0;
break;
case '2':
print_console = 1;
console_type = CONSOLE_PRINT_PREVIOUS;
print_defaults = 0; print_defaults = 0;
break; break;
case 'C': case 'C':
@ -1383,7 +1403,7 @@ int main(int argc, char** argv)
die("Table not found.\n"); die("Table not found.\n");
if (print_console) if (print_console)
dump_console(one_boot_only); dump_console(console_type);
if (print_coverage) if (print_coverage)
dump_coverage(); dump_coverage();