flashrom.c: Change doit() signature to receive buffers

Changes doit() to receive buffers directly instead of file pointers.

BUG=b:180556238
BRANCH=none
TEST=emerge flashrom

Signed-off-by: Daniel Campello <campello@chromium.org>
Change-Id: Iad006ec6a058db8eacf54a21bfb2db391383c23a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+/2775883
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Sam McNally <sammc@chromium.org>
diff --git a/flashrom.c b/flashrom.c
index 81a7890..d43ff24 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -2485,27 +2485,21 @@
  *
  * @flash	  pointer to the flash context matching the chip detected
  *		  during initialization.
- * @force         when set proceed even if the chip is not known to work
- * @filename      pointer to the name of the file to read from or write to
- * @write_it      when true, flash is programmed with 'filename' contents
+ * @buffer        pointer to the buffer to read from
+ * @write_it      when true, flash is programmed with 'buffer' contents
  * @erase_it      when true, flash chip is erased
- * @extract_it    extract all known flash chip regions into separate files
- * @diff_file	  when deciding what areas to program, use this file's
+ * @diff_buffer	  when deciding what areas to program, use this buffer
  *                contents instead of reading the current chip contents
- * @do_diff	  when true - compare result of the operation with either the
- *		  original chip contents for 'diff_file' contents, is present.
- *		  When false - do not diff, consider the chip erased before
- *		  operation starts.
  *
- * Only one of 'read_it', 'write_it', and 'erase_it' is expected to be set,
+ * Only one of 'write_it', and 'erase_it' is expected to be set,
  * but this is not enforced.
  *
- * 'do_diff' must be set if 'diff_file' is set. If 'do_diff' is set, but
- * 'diff_file' is not - comparison is done against the pre-operation chip
- * contents.
+ * If 'diff_buffer' is not set - comparison is done against flash->diff_file
+ * contents and if that is also unset comparison is done against the
+ * pre-operation chip contents.
  */
-static int doit(struct flashctx *flash, const char *filename,
-	 int write_it, int erase_it, const char *diff_file)
+static int doit(struct flashctx *flash, const void *const buffer,
+	 int write_it, int erase_it, const void *const diff_buffer)
 {
 	uint8_t *oldcontents;
 	uint8_t *newcontents;
@@ -2528,37 +2522,18 @@
 		msg_gerr("Out of memory!\n");
 		exit(1);
 	}
-	/* Assume best case: All blocks are erased. */
-	memset(newcontents, ERASED_VALUE(flash), size);
+	if (buffer) {
+		memcpy(newcontents, buffer, size);
+	} else {
+		/* Assume best case: All blocks are erased. */
+		memset(newcontents, ERASED_VALUE(flash), size);
+	}
 	/* Side effect of the assumptions above: Default write action is erase
 	 * because newcontents looks like a completely erased chip, and
 	 * oldcontents being completely unerased means we have to erase
 	 * everything before we can write.
 	 */
 
-	if ((write_it || verify) && !erase_it) {
-		/*
-		 * Note: This must be done before any files specified by -i
-		 * arguments are processed merged into the newcontents since
-		 * -i files take priority. See http://crbug.com/263495.
-		 */
-		if (filename) {
-			if (read_buf_from_file(newcontents, size, filename)) {
-				ret = 1;
-				goto out;
-			}
-		} else {
-			/* Content will be read from -i args, so they must
-			 * not overlap. */
-			if (included_regions_overlap()) {
-				msg_gerr("Error: Included regions must "
-						"not overlap.\n");
-				ret = 1;
-				goto out;
-			}
-		}
-	}
-
 	if (flash->flags.do_diff) {
 		/*
 		 * Obtain a reference image so that we can check whether
@@ -2566,9 +2541,11 @@
 		 * case write fails. If --fast-verify is used then only the
 		 * regions which are included using -i will be read.
 		 */
-		if (diff_file) {
+		if (diff_buffer) {
+			memcpy(oldcontents, diff_buffer, size);
+		} else if (flash->diff_file) {
 			msg_cdbg("Reading old contents from file... ");
-			if (read_buf_from_file(oldcontents, size, diff_file)) {
+			if (read_buf_from_file(oldcontents, size, flash->diff_file)) {
 				ret = 1;
 				msg_cdbg("FAILED.\n");
 				goto out;
@@ -2724,7 +2701,7 @@
 	if (prepare_flash_access(flash, false, false, true, false))
 		return 1;
 
-	int ret = doit(flash, NULL, false, true, flash->diff_file);
+	int ret = doit(flash, NULL, false, true, NULL);
 
 	/*
 	 * FIXME: Do we really want the scary warning if erase failed?
@@ -2742,23 +2719,74 @@
 
 int do_write(struct flashctx *const flash, const char *const filename, const char *const referencefile)
 {
-	if (prepare_flash_access(flash, false, true, false, flash->flags.verify_after_write))
-		return 1;
+	const size_t flash_size = flash->chip->total_size * 1024;
+	int ret = 1;
 
-	int ret = doit(flash, filename, true, false, referencefile);
+	uint8_t *const newcontents = filename ? malloc(flash_size) : NULL;
+	uint8_t *const refcontents = referencefile ? malloc(flash_size) : NULL;
+
+	if ((filename && !newcontents) || (referencefile && !refcontents)) {
+		msg_gerr("Out of memory!\n");
+		goto _free_ret;
+	}
+
+	if (filename) {
+		if (read_buf_from_file(newcontents, flash_size, filename))
+			goto _free_ret;
+	} else {
+		/* Content will be read from -i args, so they must not overlap. */
+		if (included_regions_overlap()) {
+			msg_gerr("Error: Included regions must not overlap.\n");
+			goto _free_ret;
+		}
+	}
+
+	if (referencefile) {
+		if (read_buf_from_file(refcontents, flash_size, referencefile))
+			goto _free_ret;
+	}
+
+	if (prepare_flash_access(flash, false, true, false, flash->flags.verify_after_write))
+		goto _free_ret;
+	ret = doit(flash, newcontents, true, false, refcontents);
 	finalize_flash_access(flash);
 
+_free_ret:
+	free(refcontents);
+	free(newcontents);
 	return ret;
 }
 
 int do_verify(struct flashctx *const flash, const char *const filename)
 {
-	if (prepare_flash_access(flash, false, false, false, true))
-		return 1;
+	const size_t flash_size = flash->chip->total_size * 1024;
+	int ret = 1;
 
-	int ret = doit(flash, filename, false, false, flash->diff_file);
+	uint8_t *const newcontents = filename ? malloc(flash_size) : NULL;
+	if (filename && !newcontents) {
+		msg_gerr("Out of memory!\n");
+		goto _free_ret;
+	}
+
+	if (filename) {
+		if (read_buf_from_file(newcontents, flash_size, filename))
+			goto _free_ret;
+	} else {
+		/* Content will be read from -i args, so they must not overlap. */
+		if (included_regions_overlap()) {
+			msg_gerr("Error: Included regions must not overlap.\n");
+			goto _free_ret;
+		}
+	}
+
+	if (prepare_flash_access(flash, false, false, false, true))
+		goto _free_ret;
+
+	ret = doit(flash, newcontents, false, false, NULL);
 	finalize_flash_access(flash);
 
+_free_ret:
+	free(newcontents);
 	return ret;
 }