@@ -58,12 +58,20 @@ static int verbose = 0;
5858#define debug (x ...) if(verbose) printf(x)
5959
6060/* File handle used to access /dev/mem */
61- static int mem_fd ;
61+ static int mem_fd = -1 ;
6262static struct mapping lbtable_mapping ;
6363
64+ /* File handle used to parse CBMEM from file instead of RAM */
65+ static int file_fd = -1 ;
66+
6467/* TSC frequency from the LB_TAG_TSC_INFO record. 0 if not present. */
6568static uint32_t tsc_freq_khz = 0 ;
6669
70+ static struct lb_cbmem_ref timestamps ;
71+ static struct lb_cbmem_ref console ;
72+ static struct lb_cbmem_ref tcpa_log ;
73+ static struct lb_memory_range cbmem ;
74+
6775static void die (const char * msg )
6876{
6977 if (msg )
@@ -101,40 +109,74 @@ static void *mapping_virt(const struct mapping *mapping)
101109static void * map_memory_with_prot (struct mapping * mapping ,
102110 unsigned long long phys , size_t sz , int prot )
103111{
104- void * v ;
105- unsigned long long page_size ;
112+ if (file_fd < 0 ) {
113+ void * v ;
114+ unsigned long long page_size ;
106115
107- page_size = system_page_size ();
116+ page_size = system_page_size ();
108117
109- mapping -> virt = NULL ;
110- mapping -> offset = phys % page_size ;
111- mapping -> virt_size = sz + mapping -> offset ;
112- mapping -> size = sz ;
113- mapping -> phys = phys ;
114-
115- if (size_to_mib (mapping -> virt_size ) == 0 ) {
116- debug ("Mapping %zuB of physical memory at 0x%llx (requested 0x%llx).\n" ,
117- mapping -> virt_size , phys - mapping -> offset , phys );
118- } else {
119- debug ("Mapping %zuMB of physical memory at 0x%llx (requested 0x%llx).\n" ,
120- size_to_mib (mapping -> virt_size ), phys - mapping -> offset ,
121- phys );
122- }
118+ mapping -> virt = NULL ;
119+ mapping -> offset = phys % page_size ;
120+ mapping -> virt_size = sz + mapping -> offset ;
121+ mapping -> size = sz ;
122+ mapping -> phys = phys ;
123123
124- v = mmap (NULL , mapping -> virt_size , prot , MAP_SHARED , mem_fd ,
125- phys - mapping -> offset );
124+ if (size_to_mib (mapping -> virt_size ) == 0 ) {
125+ debug ("Mapping %zuB of physical memory at 0x%llx (requested 0x%llx).\n" ,
126+ mapping -> virt_size , phys - mapping -> offset , phys );
127+ } else {
128+ debug ("Mapping %zuMB of physical memory at 0x%llx (requested 0x%llx).\n" ,
129+ size_to_mib (mapping -> virt_size ), phys - mapping -> offset ,
130+ phys );
131+ }
126132
127- if (v == MAP_FAILED ) {
128- debug ("Mapping failed %zuB of physical memory at 0x%llx.\n" ,
129- mapping -> virt_size , phys - mapping -> offset );
130- return NULL ;
131- }
133+ v = mmap (NULL , mapping -> virt_size , prot , MAP_SHARED , mem_fd ,
134+ phys - mapping -> offset );
135+
136+ if (v == MAP_FAILED ) {
137+ debug ("Mapping failed %zuB of physical memory at 0x%llx.\n" ,
138+ mapping -> virt_size , phys - mapping -> offset );
139+ return NULL ;
140+ }
141+
142+ mapping -> virt = v ;
143+
144+ if (mapping -> offset != 0 )
145+ debug (" ... padding virtual address with 0x%zx bytes.\n" ,
146+ mapping -> offset );
147+ } else {
148+ ssize_t ret ;
149+ mapping -> virt = malloc (sz );
150+ mapping -> offset = 0 ;
151+ mapping -> virt_size = sz ;
152+ mapping -> size = sz ;
153+ mapping -> phys = phys ;
154+
155+ debug ("map_memory phys = %llx, size = %zuB, cbmem.start = %lx\n" , phys , sz , cbmem .start );
156+
157+ if (mapping -> virt == NULL ) {
158+ debug ("Couldn't allocate %zuB of memory.\n" , sz );
159+ return NULL ;
160+ }
132161
133- mapping -> virt = v ;
162+ if (lseek (file_fd , mapping -> phys - cbmem .start , SEEK_SET ) < 0 ) {
163+ debug ("Couldn't read file from offset %llx.\n" ,
164+ mapping -> phys - cbmem .start );
165+ free (mapping -> virt );
166+ return NULL ;
167+ }
134168
135- if (mapping -> offset != 0 )
136- debug (" ... padding virtual address with 0x%zx bytes.\n" ,
137- mapping -> offset );
169+ ret = read (file_fd , mapping -> virt , sz );
170+ if (ret < 0 ) {
171+ debug ("Error reading file: %s\n" , strerror (errno ));
172+ free (mapping -> virt );
173+ return NULL ;
174+ }
175+ if ((size_t )ret != sz ) {
176+ debug ("Truncated read from offset %llx, requested %zuB, got %zuB.\n" ,
177+ mapping -> phys - cbmem .start , sz , ret );
178+ }
179+ }
138180
139181 return mapping_virt (mapping );
140182}
@@ -153,7 +195,11 @@ static int unmap_memory(struct mapping *mapping)
153195 if (mapping -> virt == NULL )
154196 return -1 ;
155197
156- munmap (mapping -> virt , mapping -> virt_size );
198+ if (file_fd < 0 )
199+ munmap (mapping -> virt , mapping -> virt_size );
200+ else
201+ free (mapping -> virt );
202+
157203 mapping -> virt = NULL ;
158204 mapping -> offset = 0 ;
159205 mapping -> virt_size = 0 ;
@@ -265,11 +311,6 @@ static int find_cbmem_entry(uint32_t id, uint64_t *addr, size_t *size)
265311 * none found.
266312 */
267313
268- static struct lb_cbmem_ref timestamps ;
269- static struct lb_cbmem_ref console ;
270- static struct lb_cbmem_ref tcpa_log ;
271- static struct lb_memory_range cbmem ;
272-
273314/* This is a work-around for a nasty problem introduced by initially having
274315 * pointer sized entries in the lb_cbmem_ref structures. This caused problems
275316 * on 64bit x86 systems because coreboot is 32bit on those systems.
@@ -1340,6 +1381,7 @@ static void print_usage(const char *name, int exit_code)
13401381 " -S | --stacked-timestamps: print stacked timestamps (e.g. for flame graph tools)\n"
13411382 " -a | --add-timestamp ID: append timestamp with ID\n"
13421383 " -L | --tcpa-log print TCPA log\n"
1384+ " -f | --file FILE: read CBMEM from FILE instead of memory\n"
13431385 " -V | --verbose: verbose (debugging) output\n"
13441386 " -v | --version: print the version\n"
13451387 " -h | --help: print this help\n"
@@ -1493,12 +1535,13 @@ int main(int argc, char** argv)
14931535 {"add-timestamp" , required_argument , 0 , 'a' },
14941536 {"hexdump" , 0 , 0 , 'x' },
14951537 {"rawdump" , required_argument , 0 , 'r' },
1538+ {"file" , required_argument , 0 , 'f' },
14961539 {"verbose" , 0 , 0 , 'V' },
14971540 {"version" , 0 , 0 , 'v' },
14981541 {"help" , 0 , 0 , 'h' },
14991542 {0 , 0 , 0 , 0 }
15001543 };
1501- while ((opt = getopt_long (argc , argv , "c12B:CltTSa:LxVvh?r:" ,
1544+ while ((opt = getopt_long (argc , argv , "c12B:CltTSa:LxVvh?r:f: " ,
15021545 long_options , & option_index )) != EOF ) {
15031546 switch (opt ) {
15041547 case 'c' :
@@ -1539,6 +1582,14 @@ int main(int argc, char** argv)
15391582 print_defaults = 0 ;
15401583 rawdump_id = strtoul (optarg , NULL , 16 );
15411584 break ;
1585+ case 'f' :
1586+ file_fd = open (optarg , O_RDONLY , 0 );
1587+ if (file_fd < 0 ) {
1588+ fprintf (stderr , "Failed to open file '%s': %s\n" ,
1589+ optarg , strerror (errno ));
1590+ return 1 ;
1591+ }
1592+ break ;
15421593 case 't' :
15431594 timestamp_type = TIMESTAMPS_PRINT_NORMAL ;
15441595 print_defaults = 0 ;
@@ -1580,11 +1631,13 @@ int main(int argc, char** argv)
15801631 print_usage (argv [0 ], 1 );
15811632 }
15821633
1583- mem_fd = open ("/dev/mem" , timestamp_id ? O_RDWR : O_RDONLY , 0 );
1584- if (mem_fd < 0 ) {
1585- fprintf (stderr , "Failed to gain memory access: %s\n" ,
1586- strerror (errno ));
1587- return 1 ;
1634+ if (file_fd < 0 ) {
1635+ mem_fd = open ("/dev/mem" , timestamp_id ? O_RDWR : O_RDONLY , 0 );
1636+ if (mem_fd < 0 ) {
1637+ fprintf (stderr , "Failed to gain memory access: %s\n" ,
1638+ strerror (errno ));
1639+ return 1 ;
1640+ }
15881641 }
15891642
15901643#if defined(__arm__ ) || defined(__aarch64__ )
@@ -1681,6 +1734,10 @@ int main(int argc, char** argv)
16811734
16821735 unmap_memory (& lbtable_mapping );
16831736
1684- close (mem_fd );
1737+ if (file_fd >= 0 )
1738+ close (file_fd );
1739+ if (mem_fd >= 0 )
1740+ close (mem_fd );
1741+
16851742 return 0 ;
16861743}
0 commit comments