layout: Verify that regions to be written are granularity aligned

This will be important with the new erase/write strategy when we don't
write per erase block anymore.

Change-Id: Ie3c74ff4313c9d72ac92d3226804e0407088c17d
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72546
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/flashrom.c b/flashrom.c
index 4258018..2b5c571 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -401,7 +401,7 @@
 	return ret;
 }
 
-static size_t gran_to_bytes(const enum write_granularity gran)
+size_t gran_to_bytes(const enum write_granularity gran)
 {
 	switch (gran) {
 		case write_gran_1bit:			return 1;
@@ -1488,7 +1488,7 @@
 		return 1;
 	}
 
-	if (layout_sanity_checks(flash)) {
+	if (layout_sanity_checks(flash, write_it)) {
 		msg_cerr("Requested regions can not be handled. Aborting.\n");
 		return 1;
 	}
diff --git a/include/flash.h b/include/flash.h
index 38e583a..db19566 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -93,6 +93,8 @@
 	write_gran_1byte_implicit_erase, /* EEPROMs and other chips with implicit erase and 1-byte writes. */
 };
 
+size_t gran_to_bytes(enum write_granularity);
+
 /*
  * How many different contiguous runs of erase blocks with one size each do
  * we have for a given erase function?
diff --git a/include/layout.h b/include/layout.h
index d2e3d74..91a6d6e 100644
--- a/include/layout.h
+++ b/include/layout.h
@@ -61,6 +61,6 @@
 const struct romentry *layout_next_included_region(const struct flashrom_layout *, chipoff_t);
 const struct romentry *layout_next_included(const struct flashrom_layout *, const struct romentry *);
 const struct romentry *layout_next(const struct flashrom_layout *, const struct romentry *);
-int layout_sanity_checks(const struct flashrom_flashctx *);
+int layout_sanity_checks(const struct flashrom_flashctx *, bool write_it);
 
 #endif /* !__LAYOUT_H__ */
diff --git a/layout.c b/layout.c
index d645078..4a5c276 100644
--- a/layout.c
+++ b/layout.c
@@ -197,10 +197,11 @@
 	}
 }
 
-int layout_sanity_checks(const struct flashrom_flashctx *const flash)
+int layout_sanity_checks(const struct flashrom_flashctx *const flash, const bool write_it)
 {
 	const struct flashrom_layout *const layout = get_layout(flash);
 	const chipsize_t total_size = flash->chip->total_size * 1024;
+	const size_t gran = gran_to_bytes(flash->chip->gran);
 	int ret = 0;
 
 	const struct romentry *entry = NULL;
@@ -216,6 +217,11 @@
 				  entry->name);
 			ret = 1;
 		}
+		if (write_it && entry->included && (entry->start % gran || (entry->end + 1) % gran)) {
+			msg_gerr("Error: Region \"%s\" is not aligned with write granularity (%zuB).\n",
+				 entry->name, gran);
+			ret = 1;
+		}
 	}
 
 	return ret;