Stefan Reinauer has uploaded this change for review. ( https://review.coreboot.org/c/em100/+/48729 )
Change subject: Add SPI trace map support ......................................................................
Add SPI trace map support
with -M you can specify a map file that will be used to print which section of the flash your SPI accesses go to. The format of the map file is simple:
Start (hex) End (hex) Length (hex) Area Name ----------- --------- ------------ --------- 00000000 01FFFFFF 02000000 Full Flash Image 00000000 00000FFF 00001000 Descriptor Region 00000014 00000017 00000004 FLMAP0 - Flash Map 0 Register 00000018 0000001B 00000004 FLMAP1 - Flash Map 1 Register [..] 00500000 01FFFFFF 01B00000 BIOS Region 00500000 00cfffff 00800000 RW_SECTION_A 00500000 0050ffff 00010000 VBLOCK_A 00510000 009fffbf 004effc0 FW_MAIN_A 009fffc0 009fffff 00000040 RW_FWID_A [..] 01805000 01874fff 00070000 GBB 01875000 01ffffff 0078b000 COREBOOT
Right now the section is only printed in brief mode.
Signed-off-by: Stefan Reinauer stefan.reinauer@coreboot.org Change-Id: Ide04eb620ad213f9b8457bec7cd57daef6b5c671 --- M Makefile M em100.c M em100.h A map.c M trace.c 5 files changed, 166 insertions(+), 5 deletions(-)
git pull ssh://review.coreboot.org:29418/em100 refs/changes/29/48729/1
diff --git a/Makefile b/Makefile index 1248780..075518d 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@
XZ = xz/xz_crc32.c xz/xz_crc64.c xz/xz_dec_bcj.c xz/xz_dec_lzma2.c xz/xz_dec_stream.c SOURCES = em100.c firmware.c fpga.c hexdump.c sdram.c spi.c system.c trace.c usb.c -SOURCES += image.c curl.c chips.c tar.c $(XZ) +SOURCES += map.c image.c curl.c chips.c tar.c $(XZ) OBJECTS = $(SOURCES:.c=.o)
all: dep em100 diff --git a/em100.c b/em100.c index 7a6f910..d7afc34 100644 --- a/em100.c +++ b/em100.c @@ -791,6 +791,7 @@ {"traceconsole", 0, 0, 'R'}, {"length", 1, 0, 'L'}, {"brief", 0, 0, 'b'}, + {"map-file", 1, 0, 'M'}, {"compatible", 0, 0, 'C'}, {NULL, 0, 0, 0} }; @@ -814,6 +815,7 @@ " -R|--traceconsole: trace console mode\n" " -L|--length HEX_VAL: length of buffer for traceconsole mode\n" " -b|--brief: brief mode for traces\n" + " -M|--map-file: Map file for trace mode\n" " -F|--firmware-update FILE|auto: update EM100pro firmware (dangerous)\n" " -f|--firmware-dump FILE: export raw EM100pro firmware to file\n" " -g|--firmware-write FILE: export EM100pro firmware to DPFW file\n" @@ -836,6 +838,7 @@ const char *desiredchip = NULL; const char *serialno = NULL; const char *filename = NULL, *read_filename = NULL; + const char *trace_mapfile = NULL; const char *firmware_in = NULL, *firmware_out = NULL; const char *holdpin = NULL; int do_start = 0, do_stop = 0; @@ -850,7 +853,7 @@ struct sigaction signal_action; struct em100 *em100 = &em100_state;
- while ((opt = getopt_long(argc, argv, "c:d:a:m:u:rsvtO:F:f:g:S:V:p:DCx:lUhTRL:b", + while ((opt = getopt_long(argc, argv, "c:d:a:m:u:rsvtO:F:f:g:S:V:p:DCx:lUhTRL:M:b", longopts, &idx)) != -1) { switch (opt) { case 'c': @@ -935,6 +938,13 @@ case 'b': trace_brief = 1; break; + case 'M': + if(access(optarg, F_OK ) == 0) + trace_mapfile = optarg; + else + printf("Can't open '%s'.\n", optarg); + break; + case 'C': compatibility = 1; break; @@ -1234,6 +1244,10 @@ if (!do_start && !do_stop) set_state(em100, 1);
+ if(trace && trace_mapfile) { + load_trace_mapfile(trace_mapfile); + } + printf ("Starting ");
if (trace || traceconsole) { diff --git a/em100.h b/em100.h index 4ba78a9..21d4324 100644 --- a/em100.h +++ b/em100.h @@ -176,6 +176,10 @@ int read_spi_trace_console(struct em100 *em100, unsigned long addr_offset, unsigned long addr_len);
+/* map.c */ +int load_trace_mapfile(const char *trace_mapfile); +void print_mapping(uint64_t addr, int full); + /* Archive handling */ typedef struct { unsigned char *address; diff --git a/map.c b/map.c new file mode 100644 index 0000000..5e1651c --- /dev/null +++ b/map.c @@ -0,0 +1,139 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "em100.h" + +#define MAX_LINE 256 + +//#define NEED_PREV + +typedef struct map_entry { + struct map_entry *next; +#ifdef NEED_PREV + struct map_entry *prev; +#endif + uint64_t start; + uint64_t end; + uint64_t len; + char name[MAX_LINE]; +} map_entry_t; + +static map_entry_t *map_entries = NULL; +static map_entry_t *map_entries_top = NULL; + +int load_trace_mapfile(const char *trace_mapfile) +{ + FILE *file; + char current_line[MAX_LINE]; + + file = fopen(trace_mapfile, "r"); + if (!file) { + perror(trace_mapfile); + return -1; + } + + while (fgets(current_line, sizeof(current_line), file) != NULL) { + unsigned long start, end, length; + const char d[] = " \t"; + char *num; + + //printf("%03ld: %s", strlen(current_line), current_line); + num = strtok(current_line, d); + if (!num) continue; + start = strtol(num, NULL, 16); + num = strtok(NULL, d); + if (!num) continue; + end = strtol(num, NULL, 16); + num = strtok(NULL, d); + if (!num) continue; + length = strtol(num, NULL, 16); + num = strtok(NULL, "\r\n"); + if (!num) continue; + while (isspace(*num)) num++; + + if ((start + length - 1 ) != end) { + continue; + } + + map_entry_t *tmp = malloc(sizeof(map_entry_t)); + if (!tmp) + continue; + + tmp->start = start; + tmp->end=end; + tmp->len=length; + strncpy(tmp->name, num, MAX_LINE - 1); + + if(!map_entries) + map_entries = tmp; + +#ifdef NEED_PREV + tmp->prev = map_entries_top; +#endif + tmp->next = NULL; + + if (map_entries_top) + map_entries_top->next=tmp; + map_entries_top = tmp; + } + +#ifdef TEST + map_entry_t *m; +#ifdef NEED_PREV + printf("Backwards\n"); + for (m=map_entries_top; m; m=m->prev) + printf("[%08lx][%08lx][%08lx]:[%s]\n", m->start, m->end, m->len, m->name); +#endif + + printf("Forwards\n"); + for (m=map_entries; m; m=m->next) + printf("[%08lx][%08lx][%08lx]:[%s]\n", m->start, m->end, m->len, m->name); +#endif + + fclose(file); + return 0; +} + +void print_mapping(uint64_t addr, int full) +{ + /* The whole purpose of strncat is to not copy the + * whole string. Apparently GCC lost its mind warning + * about that + */ +#if (__GNUC__ > 8) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wstringop-truncation" +#endif + char path[MAX_LINE] = "\0"; + + map_entry_t *m, *match = NULL; + for (m=map_entries; m; m=m->next) { + if (addr >= m->start && addr <= m->end) { + /* First one is "Flash Image", ignore that */ + if(match && full) { + int max_len = MAX_LINE - strlen(path) - 5; + strncat(path, " ‣ ", 5); + strncat(path, m->name, max_len); + } + match=m; + } + } + + if (!full && match) + strncat(path, match->name, MAX_LINE - 2); + + if(strlen(path) == 0) + strncat(path, "No match", MAX_LINE - 1); +#if (__GNUC__ > 8) +# pragma GCC diagnostic pop +#endif + +#ifdef TEST + printf("[%lx]", addr); +#endif + printf("%s", path); +#ifdef TEST + printf("\n"); +#endif +} diff --git a/trace.c b/trace.c index c04afcc..e1f065f 100644 --- a/trace.c +++ b/trace.c @@ -288,10 +288,14 @@ if (start_timestamp) start_timestamp = 0;
- if (spi_cmd_vals->address_type != ADDR_NONE) - printf("0x%02x @ 0x%08lx (%s)\n", + if (spi_cmd_vals->address_type != ADDR_NONE) { + printf("0x%02x @ 0x%08lx (%s)", spi_command, address, spi_cmd_vals->cmd_name); - else + /* No section parsing for SFDP commands */ + if (spi_cmd_vals->address_type != ADDR_NO_OFF_3B) + print_mapping(address, 1); + printf("\n"); + } else printf("0x%02x (%s)\n", spi_command, spi_cmd_vals->cmd_name); } else {