Automatically round address ranges requested from rphysmap() to page
boundaries. Other physmap() variants were not changed so this is
safe regarding unmapping.

I had also to shorten the readbility defines for the physmap_common
parameters to make the calls fit a single line.

Signed-off-by: Stefan Tauner <[email protected]>
---
 physmap.c |   61 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 40 insertions(+), 21 deletions(-)

diff --git a/physmap.c b/physmap.c
index 3811824..4f82d0f 100644
--- a/physmap.c
+++ b/physmap.c
@@ -218,12 +218,35 @@ void physunmap(void *virt_addr, size_t len)
 }
 #endif
 
-#define PHYSMAP_NOFAIL         0
-#define PHYSMAP_MAYFAIL                1
-#define PHYSMAP_RW             0
-#define PHYSMAP_RO             1
-#define PHYSMAP_NOCLEANUP      0
-#define PHYSMAP_CLEANUP                1
+#define PHYSM_NOFAIL   0
+#define PHYSM_MAYFAIL  1
+#define PHYSM_RW       0
+#define PHYSM_RO       1
+#define PHYSM_NOCLEANUP        0
+#define PHYSM_CLEANUP  1
+#define PHYSM_EXACT    0
+#define PHYSM_ROUND    1
+
+/* Round start to nearest page boundary below and set len so that the resulting
+ * address range ends at the lowest possible page boundary where the original
+ * address range is still entirely contained. It returns the difference between
+ * the rounded start address and the original start address. */
+static uintptr_t round_to_page_boundaries(uintptr_t *start, size_t *len)
+{
+       uintptr_t page_size = getpagesize();
+       uintptr_t page_mask = ~(page_size-1);
+       uintptr_t end = *start + *len;
+       uintptr_t old_start = *start;
+       msg_gspew("page_size=%" PRIxPTR "\n", page_size);
+       msg_gspew("pre-rounding:  start=0x%0*" PRIxPTR ", len=0x%0zx, 
end=0x%0*" PRIxPTR "\n",
+                 PRIxPTR_WIDTH, *start, *len, PRIxPTR_WIDTH, end);
+       *start = *start & page_mask;
+       end = (end + page_size - 1) & page_mask;
+       *len = end - *start;
+       msg_gspew("post-rounding: start=0x%0*" PRIxPTR ", len=0x%0zx, 
end=0x%0*" PRIxPTR "\n",
+                 PRIxPTR_WIDTH, *start, *len, PRIxPTR_WIDTH, *start + *len);
+       return old_start - *start;
+}
 
 struct undo_physmap_data {
        void *virt_addr;
@@ -243,24 +266,18 @@ static int undo_physmap(void *data)
 }
 
 static void *physmap_common(const char *descr, uintptr_t phys_addr, size_t 
len, bool mayfail,
-                           bool readonly, bool autocleanup)
+                           bool readonly, bool autocleanup, bool round)
 {
        void *virt_addr;
+       uintptr_t offset = 0;
 
        if (len == 0) {
                msg_pspew("Not mapping %s, zero size at 0x%0*" PRIxPTR ".\n", 
descr, PRIxPTR_WIDTH, phys_addr);
                return ERROR_PTR;
        }
 
-       if ((getpagesize() - 1) & len) {
-               msg_perr("Mapping %s at 0x%08lx, unaligned size 0x%lx.\n",
-                        descr, phys_addr, (unsigned long)len);
-       }
-
-       if ((getpagesize() - 1) & phys_addr) {
-               msg_perr("Mapping %s, 0x%lx bytes at unaligned 0x%08lx.\n",
-                        descr, (unsigned long)len, phys_addr);
-       }
+       if (round)
+               offset = round_to_page_boundaries(&phys_addr, &len);
 
        if (readonly)
                virt_addr = sys_physmap_ro_cached(phys_addr, len);
@@ -286,7 +303,9 @@ static void *physmap_common(const char *descr, uintptr_t 
phys_addr, size_t len,
                         "and reboot, or reboot into\n"
                         "single user mode.\n");
 #endif
-               if (!mayfail)
+               if (mayfail)
+                       return ERROR_PTR;
+               else
                        exit(3);
        }
 
@@ -305,7 +324,7 @@ static void *physmap_common(const char *descr, uintptr_t 
phys_addr, size_t len,
                }
        }
 
-       return virt_addr;
+       return virt_addr + offset;
 unmap_out:
        physunmap(virt_addr, len);
        if (!mayfail)
@@ -315,17 +334,17 @@ unmap_out:
 
 void *physmap(const char *descr, uintptr_t phys_addr, size_t len)
 {
-       return physmap_common(descr, phys_addr, len, PHYSMAP_NOFAIL, 
PHYSMAP_RW, PHYSMAP_NOCLEANUP);
+       return physmap_common(descr, phys_addr, len, PHYSM_NOFAIL, PHYSM_RW, 
PHYSM_NOCLEANUP, PHYSM_EXACT);
 }
 
 void *rphysmap(const char *descr, uintptr_t phys_addr, size_t len)
 {
-       return physmap_common(descr, phys_addr, len, PHYSMAP_NOFAIL, 
PHYSMAP_RW, PHYSMAP_CLEANUP);
+       return physmap_common(descr, phys_addr, len, PHYSM_NOFAIL, PHYSM_RW, 
PHYSM_CLEANUP, PHYSM_ROUND);
 }
 
 void *physmap_try_ro(const char *descr, uintptr_t phys_addr, size_t len)
 {
-       return physmap_common(descr, phys_addr, len, PHYSMAP_MAYFAIL, 
PHYSMAP_RO, PHYSMAP_NOCLEANUP);
+       return physmap_common(descr, phys_addr, len, PHYSM_MAYFAIL, PHYSM_RO, 
PHYSM_NOCLEANUP, PHYSM_EXACT);
 }
 
 #if defined(__i386__) || defined(__x86_64__)
-- 
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to