nvramtool: reduce memory mapping
Instead of trying to map the first megabyte, only map what is required to read the tables. Change-Id: I9139dbc8fd1dd768bef7ab85c27cd4c18e2931b3 Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com> Reviewed-on: http://review.coreboot.org/2485 Tested-by: build bot (Jenkins) Reviewed-by: Peter Stuge <peter@stuge.se>
This commit is contained in:
parent
fbf078311f
commit
12781422d5
|
@ -200,19 +200,15 @@ static const mem_range_t mem_ranges[NUM_MEM_RANGES] =
|
||||||
{0x000f0000, 0x000fffff}
|
{0x000f0000, 0x000fffff}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is the number of bytes of physical memory to map, starting at physical
|
|
||||||
* address 0. This value must be large enough to contain all memory ranges
|
|
||||||
* specified in mem_ranges above plus the maximum possible size of the
|
|
||||||
* coreboot table (since the start of the table could potentially occur at
|
|
||||||
* the end of the last memory range).
|
|
||||||
*/
|
|
||||||
static const size_t BYTES_TO_MAP = (1024 * 1024);
|
|
||||||
|
|
||||||
/* Pointer to low physical memory that we access by calling mmap() on
|
/* Pointer to low physical memory that we access by calling mmap() on
|
||||||
* /dev/mem.
|
* /dev/mem.
|
||||||
*/
|
*/
|
||||||
static const void *low_phys_mem;
|
static const void *low_phys_mem;
|
||||||
static unsigned long low_phys_base = 0;
|
/* impossible value since not page aligned: first map request will happen */
|
||||||
|
static unsigned long low_phys_base = 0x1;
|
||||||
|
|
||||||
|
/* count of mapped pages */
|
||||||
|
static unsigned long mapped_pages = 0;
|
||||||
|
|
||||||
/* Pointer to coreboot table. */
|
/* Pointer to coreboot table. */
|
||||||
static const struct lb_header *lbtable = NULL;
|
static const struct lb_header *lbtable = NULL;
|
||||||
|
@ -242,6 +238,37 @@ static const hexdump_format_t format =
|
||||||
#define phystov(paddr) (((unsigned long) low_phys_mem) + \
|
#define phystov(paddr) (((unsigned long) low_phys_mem) + \
|
||||||
((unsigned long) paddr) - low_phys_base)
|
((unsigned long) paddr) - low_phys_base)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* map_pages
|
||||||
|
*
|
||||||
|
* Maps just enough pages to cover base_address + length
|
||||||
|
* and updates affected variables
|
||||||
|
****************************************************************************/
|
||||||
|
static void map_pages(unsigned long base_address, unsigned long length)
|
||||||
|
{
|
||||||
|
unsigned long num_pages = (length +
|
||||||
|
(base_address & (getpagesize() - 1)) +
|
||||||
|
getpagesize() - 1) >> 12;
|
||||||
|
base_address &= ~(getpagesize() - 1);
|
||||||
|
|
||||||
|
/* no need to do anything */
|
||||||
|
if ((low_phys_base == base_address) && (mapped_pages == num_pages)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (low_phys_mem) {
|
||||||
|
munmap((void *)low_phys_mem, mapped_pages << 12);
|
||||||
|
}
|
||||||
|
if ((low_phys_mem = mmap(NULL, num_pages << 12, PROT_READ, MAP_SHARED, fd,
|
||||||
|
(off_t) base_address)) == MAP_FAILED) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Failed to mmap /dev/mem at %lx: %s\n",
|
||||||
|
prog_name, base_address, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
low_phys_base = base_address;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* get_lbtable
|
* get_lbtable
|
||||||
*
|
*
|
||||||
|
@ -264,20 +291,11 @@ void get_lbtable(void)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((low_phys_mem =
|
|
||||||
mmap(NULL, BYTES_TO_MAP, PROT_READ, MAP_SHARED, fd, 0))
|
|
||||||
== MAP_FAILED) {
|
|
||||||
fprintf(stderr, "%s: Failed to mmap /dev/mem: %s\n", prog_name,
|
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bad_header_count = 0;
|
bad_header_count = 0;
|
||||||
bad_table_count = 0;
|
bad_table_count = 0;
|
||||||
|
|
||||||
for (i = 0; i < NUM_MEM_RANGES; i++) {
|
for (i = 0; i < NUM_MEM_RANGES; i++) {
|
||||||
lbtable = lbtable_scan(phystov(mem_ranges[i].start),
|
lbtable = lbtable_scan(mem_ranges[i].start, mem_ranges[i].end,
|
||||||
phystov(mem_ranges[i].end),
|
|
||||||
&bad_headers, &bad_tables);
|
&bad_headers, &bad_tables);
|
||||||
|
|
||||||
if (lbtable != NULL)
|
if (lbtable != NULL)
|
||||||
|
@ -421,8 +439,7 @@ void list_lbtable_item(const char item[])
|
||||||
* first and last bytes of the chunk of memory to be scanned. For instance,
|
* first and last bytes of the chunk of memory to be scanned. For instance,
|
||||||
* values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
|
* values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
|
||||||
* chunk of memory starting at address 0x10000000. 'start' and 'end' are
|
* chunk of memory starting at address 0x10000000. 'start' and 'end' are
|
||||||
* virtual addresses in the address space of the current process. They
|
* physical addresses.
|
||||||
* represent a chunk of memory obtained by calling mmap() on /dev/mem.
|
|
||||||
*
|
*
|
||||||
* If a coreboot table is found, return a pointer to it. Otherwise return
|
* If a coreboot table is found, return a pointer to it. Otherwise return
|
||||||
* NULL. On return, *bad_header_count and *bad_table_count are set as
|
* NULL. On return, *bad_header_count and *bad_table_count are set as
|
||||||
|
@ -444,7 +461,7 @@ static const struct lb_header *lbtable_scan(unsigned long start,
|
||||||
static const char signature[4] = { 'L', 'B', 'I', 'O' };
|
static const char signature[4] = { 'L', 'B', 'I', 'O' };
|
||||||
const struct lb_header *table;
|
const struct lb_header *table;
|
||||||
const struct lb_forward *forward;
|
const struct lb_forward *forward;
|
||||||
const uint32_t *p;
|
unsigned long p;
|
||||||
uint32_t sig;
|
uint32_t sig;
|
||||||
|
|
||||||
assert(end >= start);
|
assert(end >= start);
|
||||||
|
@ -459,14 +476,15 @@ static const struct lb_header *lbtable_scan(unsigned long start,
|
||||||
* for 'start' and 'end': even weird boundary cases like 0x00000000 and
|
* for 'start' and 'end': even weird boundary cases like 0x00000000 and
|
||||||
* 0xffffffff on a 32-bit architecture.
|
* 0xffffffff on a 32-bit architecture.
|
||||||
*/
|
*/
|
||||||
for (p = (const uint32_t *)start;
|
map_pages(start, end - start);
|
||||||
(((unsigned long)p) <= end) &&
|
for (p = start;
|
||||||
((end - (unsigned long)p) >= (sizeof(uint32_t) - 1)); p += 4) {
|
(p <= end) &&
|
||||||
if (*p != sig)
|
(end - p >= (sizeof(uint32_t) - 1)); p += 4) {
|
||||||
|
if (*(uint32_t*)phystov(p) != sig)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* We found a valid signature. */
|
/* We found a valid signature. */
|
||||||
table = (const struct lb_header *)p;
|
table = (const struct lb_header *)phystov(p);
|
||||||
|
|
||||||
/* validate header checksum */
|
/* validate header checksum */
|
||||||
if (compute_ip_checksum((void *)table, sizeof(*table))) {
|
if (compute_ip_checksum((void *)table, sizeof(*table))) {
|
||||||
|
@ -474,6 +492,7 @@ static const struct lb_header *lbtable_scan(unsigned long start,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map_pages(p, table->table_bytes + sizeof(*table));
|
||||||
/* validate table checksum */
|
/* validate table checksum */
|
||||||
if (table->table_checksum !=
|
if (table->table_checksum !=
|
||||||
compute_ip_checksum(((char *)table) + sizeof(*table),
|
compute_ip_checksum(((char *)table) + sizeof(*table),
|
||||||
|
@ -490,22 +509,7 @@ static const struct lb_header *lbtable_scan(unsigned long start,
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
uint64_t new_phys = forward->forward;
|
uint64_t new_phys = forward->forward;
|
||||||
|
table = lbtable_scan(new_phys, new_phys + getpagesize(),
|
||||||
new_phys &= ~(getpagesize() - 1);
|
|
||||||
|
|
||||||
munmap((void *)low_phys_mem, BYTES_TO_MAP);
|
|
||||||
if ((low_phys_mem =
|
|
||||||
mmap(NULL, BYTES_TO_MAP, PROT_READ, MAP_SHARED, fd,
|
|
||||||
(off_t) new_phys)) == MAP_FAILED) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s: Failed to mmap /dev/mem: %s\n",
|
|
||||||
prog_name, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
low_phys_base = new_phys;
|
|
||||||
table =
|
|
||||||
lbtable_scan(phystov(low_phys_base),
|
|
||||||
phystov(low_phys_base + BYTES_TO_MAP),
|
|
||||||
bad_header_count, bad_table_count);
|
bad_header_count, bad_table_count);
|
||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
|
|
Loading…
Reference in New Issue