vboot_reference: Allow flashrom_read_image() reading per-region

BUG=b:207808292
BRANCH=none
TEST=`make`

Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Change-Id: I98f1a2566ef50b2c7b1376141bb2f1c096b710a6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3358664
Tested-by: Edward O'Callaghan <quasisec@chromium.org>
Auto-Submit: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Nikolai Artemiev <nartemiev@google.com>
Commit-Queue: Nikolai Artemiev <nartemiev@google.com>
diff --git a/futility/flashrom_drv.c b/futility/flashrom_drv.c
index 5ebe446..69532f4 100644
--- a/futility/flashrom_drv.c
+++ b/futility/flashrom_drv.c
@@ -52,7 +52,8 @@
 	return tmp;
 }
 
-int flashrom_read_image(struct firmware_image *image, int verbosity)
+int flashrom_read_image(struct firmware_image *image, const char *region,
+			int verbosity)
 {
 	int r = 0;
 	size_t len = 0;
@@ -64,6 +65,7 @@
 
 	struct flashrom_programmer *prog = NULL;
 	struct flashrom_flashctx *flashctx = NULL;
+	struct flashrom_layout *layout = NULL;
 
 	flashrom_set_log_callback((flashrom_log_callback *)&flashrom_print_cb);
 
@@ -72,13 +74,41 @@
 	r |= flashrom_flash_probe(&flashctx, prog, NULL);
 
 	len = flashrom_flash_getsize(flashctx);
+
+	if (region) {
+		r = flashrom_layout_read_fmap_from_buffer(
+			&layout, flashctx, (const uint8_t *)image->data,
+			image->size);
+		if (r > 0) {
+			WARN("could not read fmap from image, r=%d, "
+				"falling back to read from rom\n", r);
+			r = flashrom_layout_read_fmap_from_rom(
+				&layout, flashctx, 0, len);
+			if (r > 0) {
+				ERROR("could not read fmap from rom, r=%d\n", r);
+				r = -1;
+				goto err_cleanup;
+			}
+		}
+		// empty region causes seg fault in API.
+		r |= flashrom_layout_include_region(layout, region);
+		if (r > 0) {
+			ERROR("could not include region = '%s'\n", region);
+			r = -1;
+			goto err_cleanup;
+		}
+		flashrom_layout_set(flashctx, layout);
+	}
+
 	image->data = calloc(1, len);
 	image->size = len;
 	image->file_name = strdup("<none>");
 
 	r |= flashrom_image_read(flashctx, image->data, len);
 
+err_cleanup:
 	r |= flashrom_programmer_shutdown(prog);
+	flashrom_layout_release(layout);
 	flashrom_flash_release(flashctx);
 	free(tmp);
 
diff --git a/futility/updater_utils.c b/futility/updater_utils.c
index 936abaf..91fd07e 100644
--- a/futility/updater_utils.c
+++ b/futility/updater_utils.c
@@ -524,7 +524,7 @@
 {
 	int r;
 
-	r = flashrom_read_image(image, (verbosity + 1));
+	r = flashrom_read_image(image, NULL, (verbosity + 1));
 	if (!r)
 		r = parse_firmware_image(image);
 	return r;
diff --git a/futility/updater_utils.h b/futility/updater_utils.h
index 2d64c29..ca6771e 100644
--- a/futility/updater_utils.h
+++ b/futility/updater_utils.h
@@ -228,7 +228,8 @@
  */
 const char *get_firmware_rootkey_hash(const struct firmware_image *image);
 
-int flashrom_read_image(struct firmware_image *image, int verbosity);
+int flashrom_read_image(struct firmware_image *image, const char *region,
+			 int verbosity);
 int flashrom_write_image(const struct firmware_image *image,
 			const char *region,
 			const struct firmware_image *diff_image,