Patrick Georgi ([email protected]) just uploaded a new patch set to 
gerrit, which you can find at http://review.coreboot.org/2485

-gerrit

commit 97b58e84dfcf4b3b543ac3d75f77c5d66c91fe30
Author: Patrick Georgi <[email protected]>
Date:   Thu Feb 21 14:03:47 2013 +0100

    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 <[email protected]>
---
 util/nvramtool/lbtable.c | 90 +++++++++++++++++++++++++-----------------------
 1 file changed, 47 insertions(+), 43 deletions(-)

diff --git a/util/nvramtool/lbtable.c b/util/nvramtool/lbtable.c
index 7a968b7..5f1f22d 100644
--- a/util/nvramtool/lbtable.c
+++ b/util/nvramtool/lbtable.c
@@ -200,19 +200,15 @@ static const mem_range_t mem_ranges[NUM_MEM_RANGES] =
 {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
  * /dev/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. */
 static const struct lb_header *lbtable = NULL;
@@ -243,6 +239,37 @@ static const hexdump_format_t format =
                         ((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
  *
  * Find the coreboot table and set global variable lbtable to point to it.
@@ -264,20 +291,11 @@ void get_lbtable(void)
                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_table_count = 0;
 
        for (i = 0; i < NUM_MEM_RANGES; i++) {
-               lbtable = lbtable_scan(phystov(mem_ranges[i].start),
-                                      phystov(mem_ranges[i].end),
+               lbtable = lbtable_scan(mem_ranges[i].start, mem_ranges[i].end,
                                       &bad_headers, &bad_tables);
 
                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,
  * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
  * chunk of memory starting at address 0x10000000.  'start' and 'end' are
- * virtual addresses in the address space of the current process.  They
- * represent a chunk of memory obtained by calling mmap() on /dev/mem.
+ * physical addresses.
  *
  * 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
@@ -444,7 +461,7 @@ static const struct lb_header *lbtable_scan(unsigned long 
start,
        static const char signature[4] = { 'L', 'B', 'I', 'O' };
        const struct lb_header *table;
        const struct lb_forward *forward;
-       const uint32_t *p;
+       unsigned long p;
        uint32_t sig;
 
        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
         * 0xffffffff on a 32-bit architecture.
         */
-       for (p = (const uint32_t *)start;
-            (((unsigned long)p) <= end) &&
-            ((end - (unsigned long)p) >= (sizeof(uint32_t) - 1)); p += 4) {
-               if (*p != sig)
+       map_pages(start, end - start);
+       for (p = start;
+            (p <= end) &&
+            (end - p >= (sizeof(uint32_t) - 1)); p += 4) {
+               if (*(uint32_t*)phystov(p) != sig)
                        continue;
 
                /* We found a valid signature. */
-               table = (const struct lb_header *)p;
+               table = (const struct lb_header *)phystov(p);
 
                /* validate header checksum */
                if (compute_ip_checksum((void *)table, sizeof(*table))) {
@@ -474,6 +492,7 @@ static const struct lb_header *lbtable_scan(unsigned long 
start,
                        continue;
                }
 
+               map_pages(p, table->table_bytes + sizeof(*table));
                /* validate table checksum */
                if (table->table_checksum !=
                    compute_ip_checksum(((char *)table) + sizeof(*table),
@@ -490,22 +509,7 @@ static const struct lb_header *lbtable_scan(unsigned long 
start,
 
                if (forward) {
                        uint64_t new_phys = forward->forward;
-
-                       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),
+                       table = lbtable_scan(new_phys, new_phys + getpagesize(),
                                         bad_header_count, bad_table_count);
                }
                return table;

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to