[flashrom] [PATCH 4/4] Allow physmap_common() to round address ranges to page boundaries.

Stefan Tauner stefan.tauner at student.tuwien.ac.at
Mon Dec 31 21:53:27 CET 2012


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

This patch also changes the display width of all addresses in
physmap.c to 16 hex characters.

Signed-off-by: Stefan Tauner <stefan.tauner at student.tuwien.ac.at>
---
 physmap.c |   54 +++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 19 deletions(-)

diff --git a/physmap.c b/physmap.c
index a9445d5..e6d9a30 100644
--- a/physmap.c
+++ b/physmap.c
@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#include <inttypes.h>
 #include <unistd.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -215,6 +216,27 @@ void physunmap(void *virt_addr, size_t len)
 }
 #endif
 
+/* 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 unsigned long round_to_page_boundaries(unsigned long *start, size_t *len)
+{
+	unsigned long page_size = getpagesize();
+	unsigned long page_mask = ~(page_size-1);
+	unsigned long end = *start + *len;
+	unsigned long old_start = *start;
+	msg_gspew("page_size=%lu\n", page_size);
+	msg_gspew("pre-rounding:  start=0x%016" PRIx64 ", len=0x%0zx, end=0x%016" PRIx64 "\n",
+		  *start, *len, end);
+	*start = *start & page_mask;
+	end = (end + page_size - 1) & page_mask;
+	*len = end - *start;
+	msg_gspew("post-rounding: start=0x%016" PRIx64 ", len=0x%0zx, end=0x%016" PRIx64 "\n",
+		  *start, *len, *start + *len);
+	return old_start - *start;
+}
+
 struct physmap_stutdown_data {
 	void *addr;
 	size_t len;
@@ -233,25 +255,18 @@ static int physmap_shutdown(void *data)
 }
 
 static void *physmap_common(const char *descr, unsigned long phys_addr, size_t len, bool mayfail,
-			    bool readonly, bool autocleanup)
+			    bool readonly, bool autocleanup, bool round)
 {
 	void *virt_addr;
+	unsigned long offset = 0;
 
 	if (len == 0) {
-		msg_pspew("Not mapping %s, zero size at 0x%08lx.\n",
-			  descr, phys_addr);
+		msg_pspew("Not mapping %s, zero size at 0x%016" PRIx64 ".\n", descr, 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);
@@ -261,8 +276,7 @@ static void *physmap_common(const char *descr, unsigned long phys_addr, size_t l
 	if (ERROR_PTR == virt_addr) {
 		if (NULL == descr)
 			descr = "memory";
-		msg_perr("Error accessing %s, 0x%lx bytes at 0x%08lx\n", descr,
-			 (unsigned long)len, phys_addr);
+		msg_perr("Error accessing %s, 0x%0zx bytes at 0x%016" PRIx64 "\n", descr, len, phys_addr);
 		perror(MEM_DEV " mmap failed");
 #ifdef __linux__
 		if (EINVAL == errno) {
@@ -277,7 +291,9 @@ static void *physmap_common(const char *descr, unsigned long phys_addr, size_t l
 			 "and reboot, or reboot into\n"
 			 "single user mode.\n");
 #endif
-		if (!mayfail)
+		if (mayfail)
+			return ERROR_PTR;
+		else
 			exit(3);
 	}
 
@@ -296,7 +312,7 @@ static void *physmap_common(const char *descr, unsigned long phys_addr, size_t l
 		}
 	}
 
-	return virt_addr;
+	return virt_addr + offset;
 unmap_out:
 	physunmap(virt_addr, len);
 	return ERROR_PTR;
@@ -304,17 +320,17 @@ unmap_out:
 
 void *physmap(const char *descr, unsigned long phys_addr, size_t len)
 {
-	return physmap_common(descr, phys_addr, len, false, false, false);
+	return physmap_common(descr, phys_addr, len, false, false, false, false);
 }
 
 void *physmap_autocleanup(const char *descr, unsigned long phys_addr, size_t len)
 {
-	return physmap_common(descr, phys_addr, len, false, false, true);
+	return physmap_common(descr, phys_addr, len, false, false, true, true);
 }
 
 void *physmap_try_ro(const char *descr, unsigned long phys_addr, size_t len)
 {
-	return physmap_common(descr, phys_addr, len, true, true, false);
+	return physmap_common(descr, phys_addr, len, true, true, false, false);
 }
 
 #if defined(__i386__) || defined(__x86_64__)
-- 
Kind regards, Stefan Tauner





More information about the flashrom mailing list