physmap: Implement source-aligned version of mmio_readn()

Implement readn() with explicit alignment of the source pointer.

Change-Id: Ic754c552c826ec06ea209a039c3035265ca61c9a
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72581
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/hwaccess_physmap.c b/hwaccess_physmap.c
index cfc599e..5f18f8e 100644
--- a/hwaccess_physmap.c
+++ b/hwaccess_physmap.c
@@ -440,6 +440,29 @@
 	return;
 }
 
+/* Read source-aligned to `align` bytes. `align` should be 4 or 8. */
+void mmio_readn_aligned(const void *addr, uint8_t *dst, size_t len, size_t align)
+{
+	volatile const uint8_t *src = addr;
+
+	/* align */
+	for (; (uintptr_t)src % align && len > 0; --len, ++dst, ++src)
+		*dst = *src;
+
+	/* copy aligned */
+	if (align == 4) {
+		for (; len >= align; len -= align, dst += align, src += align)
+			*(uint32_t *)dst = *(volatile const uint32_t *)src;
+	} else if (align == 8) {
+		for (; len >= align; len -= align, dst += align, src += align)
+			*(uint64_t *)dst = *(volatile const uint64_t *)src;
+	}
+
+	/* residue */
+	for (; len > 0; --len, ++dst, ++src)
+		*dst = *src;
+}
+
 void mmio_le_writeb(uint8_t val, void *addr)
 {
 	mmio_writeb(cpu_to_le8(val), addr);