[flashrom] [PATCH 3/7] Allow physmap_common() to round address ranges to page boundaries.
Stefan Tauner
stefan.tauner at student.tuwien.ac.at
Wed Jul 10 21:21:07 CEST 2013
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 <stefan.tauner at student.tuwien.ac.at>
---
physmap.c | 61 ++++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/physmap.c b/physmap.c
index 2c90091..b248f92 100644
--- a/physmap.c
+++ b/physmap.c
@@ -208,12 +208,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;
@@ -233,24 +256,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%0*" PRIxPTR ", unaligned size 0x%lx.\n",
- descr, PRIxPTR_WIDTH, phys_addr, (unsigned long)len);
- }
-
- if ((getpagesize() - 1) & phys_addr) {
- msg_perr("Mapping %s, 0x%lx bytes at unaligned 0x%0*" PRIxPTR ".\n",
- descr, (unsigned long)len, PRIxPTR_WIDTH, phys_addr);
- }
+ if (round)
+ offset = round_to_page_boundaries(&phys_addr, &len);
if (readonly)
virt_addr = sys_physmap_ro_cached(phys_addr, len);
@@ -276,7 +293,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);
}
@@ -295,7 +314,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)
@@ -305,17 +324,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);
}
/* MSR abstraction implementations for Linux, OpenBSD, FreeBSD/Dragonfly, OSX, libpayload
--
Kind regards, Stefan Tauner
More information about the flashrom
mailing list