>From 45e0037a5e25744263b91c3164396139e137fa5e Mon Sep 17 00:00:00 2001
From: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
Date: Fri, 17 Aug 2012 19:11:35 +0200
Subject: [PATCH] Make struct flashchip a field in struct flashctx instead of
 a complete copy. --- FIXME: free...


Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
---
 82802ab.c      |   12 ++--
 cli_classic.c  |   38 ++++++-------
 en29lv640b.c   |    4 +-
 flash.h        |   28 ++--------
 flashrom.c     |  168 +++++++++++++++++++++++++++++---------------------------
 ichspi.c       |   12 ++--
 it87spi.c      |   20 +++----
 jedec.c        |   45 +++++++--------
 layout.c       |    4 +-
 m29f400bt.c    |    4 +-
 pm49fl00x.c    |    8 +--
 print.c        |   58 +++++++++----------
 programmer.h   |    2 +-
 sfdp.c         |   32 +++++------
 spi.c          |    6 +-
 spi25.c        |   42 +++++++-------
 sst28sf040.c   |    2 +-
 sst49lfxxxc.c  |    2 +-
 sst_fwhub.c    |    6 +-
 stm50flw0x0x.c |    4 +-
 w29ee011.c     |    6 +-
 w39.c          |    8 +--
 22 files changed, 246 insertions(+), 265 deletions(-)

diff --git a/82802ab.c b/82802ab.c
index 79e157a..608995d 100644
--- a/82802ab.c
+++ b/82802ab.c
@@ -44,7 +44,7 @@ int probe_82802ab(struct flashctx *flash)
 {
 	chipaddr bios = flash->virtual_memory;
 	uint8_t id1, id2, flashcontent1, flashcontent2;
-	int shifted = (flash->feature_bits & FEATURE_ADDR_SHIFTED) != 0;
+	int shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED) != 0;
 
 	/* Reset to get a clean state */
 	chip_writeb(flash, 0xFF, bios);
@@ -80,10 +80,10 @@ int probe_82802ab(struct flashctx *flash)
 		msg_cdbg(", id2 is normal flash content");
 
 	msg_cdbg("\n");
-	if (id1 != flash->manufacture_id || id2 != flash->model_id)
+	if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
 		return 0;
 
-	if (flash->feature_bits & FEATURE_REGISTERMAP)
+	if (flash->chip->feature_bits & FEATURE_REGISTERMAP)
 		map_flash_registers(flash);
 
 	return 1;
@@ -112,7 +112,7 @@ int unlock_82802ab(struct flashctx *flash)
 	int i;
 	//chipaddr wrprotect = flash->virtual_registers + page + 2;
 
-	for (i = 0; i < flash->total_size * 1024; i+= flash->page_size)
+	for (i = 0; i < flash->chip->total_size * 1024; i+= flash->chip->page_size)
 		chip_writeb(flash, 0, flash->virtual_registers + i + 2);
 
 	return 0;
@@ -181,7 +181,7 @@ int unlock_28f004s5(struct flashctx *flash)
 	}
 
 	/* Read block lock-bits */
-	for (i = 0; i < flash->total_size * 1024; i+= (64 * 1024)) {
+	for (i = 0; i < flash->chip->total_size * 1024; i+= (64 * 1024)) {
 		bcfg = chip_readb(flash, bios + i + 2); // read block lock config
 		msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un");
 		if (bcfg) {
@@ -234,7 +234,7 @@ int unlock_lh28f008bjt(struct flashctx *flash)
 	}
 
 	/* Read block lock-bits, 8 * 8 KB + 15 * 64 KB */
-	for (i = 0; i < flash->total_size * 1024;
+	for (i = 0; i < flash->chip->total_size * 1024;
 	     i += (i >= (64 * 1024) ? 64 * 1024 : 8 * 1024)) {
 		bcfg = chip_readb(flash, bios + i + 2); /* read block lock config */
 		msg_cdbg("block lock at %06x is %slocked!\n", i,
diff --git a/cli_classic.c b/cli_classic.c
index cf3874c..a639e64 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -109,9 +109,9 @@ int main(int argc, char *argv[])
 {
 	unsigned long size;
 	/* Probe for up to three flash chips. */
-	const struct flashchip *flash;
-	struct flashctx flashes[3];
+	struct flashctx flashes[3] = {{0}};
 	struct flashctx *fill_flash;
+	const struct flashchip *chip;
 	const char *name;
 	int namelen, opt, i, j;
 	int startchip = -1, chipcount = 0, option_index = 0, force = 0;
@@ -389,17 +389,17 @@ int main(int argc, char *argv[])
 	}
 	/* Does a chip with the requested name exist in the flashchips array? */
 	if (chip_to_probe) {
-		for (flash = flashchips; flash && flash->name; flash++)
-			if (!strcmp(flash->name, chip_to_probe))
+		for (chip = flashchips; chip && chip->name; chip++)
+			if (!strcmp(chip->name, chip_to_probe))
 				break;
-		if (!flash || !flash->name) {
+		if (!chip || !chip->name) {
 			msg_cerr("Error: Unknown chip '%s' specified.\n", chip_to_probe);
 			msg_gerr("Run flashrom -L to view the hardware supported in this flashrom version.\n");
 			ret = 1;
 			goto out;
 		}
 		/* Clean up after the check. */
-		flash = NULL;
+		chip = NULL;
 	}
 
 	if (prog == PROGRAMMER_INVALID) {
@@ -419,16 +419,13 @@ int main(int argc, char *argv[])
 		goto out_shutdown;
 	}
 	tempstr = flashbuses_to_text(get_buses_supported());
-	msg_pdbg("The following protocols are supported: %s.\n",
-		 tempstr);
+	msg_pdbg("The following protocols are supported: %s.\n", tempstr);
 	free(tempstr);
 
 	for (j = 0; j < registered_programmer_count; j++) {
 		startchip = 0;
 		while (chipcount < ARRAY_SIZE(flashes)) {
-			startchip = probe_flash(&registered_programmers[j],
-						startchip, 
-						&flashes[chipcount], 0);
+			startchip = probe_flash(&registered_programmers[j], startchip, &flashes[chipcount], 0);
 			if (startchip == -1)
 				break;
 			chipcount++;
@@ -437,9 +434,9 @@ int main(int argc, char *argv[])
 	}
 
 	if (chipcount > 1) {
-		msg_cinfo("Multiple flash chips were detected: \"%s\"", flashes[0].name);
+		msg_cinfo("Multiple flash chips were detected: \"%s\"", flashes[0].chip->name);
 		for (i = 1; i < chipcount; i++)
-			msg_cinfo(", \"%s\"", flashes[i].name);
+			msg_cinfo(", \"%s\"", flashes[i].chip->name);
 		msg_cinfo("\nPlease specify which chip to use with the -c <chipname> option.\n");
 		ret = 1;
 		goto out_shutdown;
@@ -456,7 +453,7 @@ int main(int argc, char *argv[])
 			/* This loop just counts compatible controllers. */
 			for (j = 0; j < registered_programmer_count; j++) {
 				pgm = &registered_programmers[j];
-				if (pgm->buses_supported & flashes[0].bustype)
+				if (pgm->buses_supported & flashes[0].chip->bustype)
 					compatible_programmers++;
 			}
 			if (compatible_programmers > 1)
@@ -481,19 +478,18 @@ int main(int argc, char *argv[])
 		goto out_shutdown;
 	} else if (!chip_to_probe) {
 		/* repeat for convenience when looking at foreign logs */
-		tempstr = flashbuses_to_text(flashes[0].bustype);
+		tempstr = flashbuses_to_text(flashes[0].chip->bustype);
 		msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n",
-			 flashes[0].vendor, flashes[0].name,
-			 flashes[0].total_size, tempstr);
+			 flashes[0].chip->vendor, flashes[0].chip->name, flashes[0].chip->total_size, tempstr);
 		free(tempstr);
 	}
 
 	fill_flash = &flashes[0];
+	chip = fill_flash->chip;
+	check_chip_supported(chip);
 
-	check_chip_supported(fill_flash);
-
-	size = fill_flash->total_size * 1024;
-	if (check_max_decode(fill_flash->pgm->buses_supported & fill_flash->bustype, size) && (!force)) {
+	size = chip->total_size * 1024;
+	if (check_max_decode(fill_flash->pgm->buses_supported & chip->bustype, size) && (!force)) {
 		msg_cerr("Chip is too big for this programmer (-V gives details). Use --force to override.\n");
 		ret = 1;
 		goto out_shutdown;
diff --git a/en29lv640b.c b/en29lv640b.c
index 0dff2d1..e79415a 100644
--- a/en29lv640b.c
+++ b/en29lv640b.c
@@ -81,7 +81,7 @@ int probe_en29lv640b(struct flashctx *flash)
 
 	msg_cdbg("%s: id1 0x%04x, id2 0x%04x\n", __func__, id1, id2);
 
-	if (id1 == flash->manufacture_id && id2 == flash->model_id)
+	if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id)
 		return 1;
 
 	return 0;
@@ -130,7 +130,7 @@ int block_erase_en29lv640b(struct flashctx *flash, unsigned int start,
 int block_erase_chip_en29lv640b(struct flashctx *flash, unsigned int address,
 			        unsigned int blocklen)
 {
-	if ((address != 0) || (blocklen != flash->total_size * 1024)) {
+	if ((address != 0) || (blocklen != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n", __func__);
 		return -1;
 	}
diff --git a/flash.h b/flash.h
index b41c281..9a03e35 100644
--- a/flash.h
+++ b/flash.h
@@ -87,6 +87,7 @@ enum chipbustype {
 #define FEATURE_WRSR_EITHER	(FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
 
 struct flashctx;
+typedef int (erasefunc_t)(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 
 struct flashchip {
 	const char *vendor;
@@ -135,7 +136,7 @@ struct flashchip {
 		} eraseblocks[NUM_ERASEREGIONS];
 		/* a block_erase function should try to erase one block of size
 		 * 'blocklen' at address 'blockaddr' and return 0 on success. */
-		int (*block_erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen);
+		erasefunc_t *block_erase;
 	} block_erasers[NUM_ERASEFUNCTIONS];
 
 	int (*printlock) (struct flashctx *flash);
@@ -148,35 +149,14 @@ struct flashchip {
 	} voltage;
 };
 
-/* struct flashctx must always contain struct flashchip at the beginning. */
 struct flashctx {
-	const char *vendor;
-	const char *name;
-	enum chipbustype bustype;
-	uint32_t manufacture_id;
-	uint32_t model_id;
-	int total_size;
-	int page_size;
-	int feature_bits;
-	uint32_t tested;
-	int (*probe) (struct flashctx *flash);
-	int probe_timing;
-	struct block_eraser block_erasers[NUM_ERASEFUNCTIONS];
-	int (*printlock) (struct flashctx *flash);
-	int (*unlock) (struct flashctx *flash);
-	int (*write) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
-	int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
-	struct voltage voltage;
-	/* struct flashchip ends here. */
-	
+	struct flashchip *chip;
 	chipaddr virtual_memory;
 	/* Some flash devices have an additional register space. */
 	chipaddr virtual_registers;
 	struct registered_programmer *pgm;
 };
 
-typedef int (erasefunc_t)(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
-
 #define TEST_UNTESTED	0
 
 #define TEST_OK_PROBE	(1 << 0)
@@ -307,7 +287,7 @@ int print(enum msglevel level, const char *fmt, ...) __attribute__((format(print
 int register_include_arg(char *name);
 int process_include_args(void);
 int read_romlayout(char *name);
-int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents);
+int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents);
 
 /* spi.c */
 struct spi_command {
diff --git a/flashrom.c b/flashrom.c
index 9544155..6329a76 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -416,7 +416,7 @@ void programmer_delay(int usecs)
 
 void map_flash_registers(struct flashctx *flash)
 {
-	size_t size = flash->total_size * 1024;
+	size_t size = flash->chip->total_size * 1024;
 	/* Flash registers live 4 MByte below the flash. */
 	/* FIXME: This is incorrect for nonstandard flashbase. */
 	flash->virtual_registers = (chipaddr)programmer_map_flash_region("flash chip registers", (0xFFFFFFFF - 0x400000 - size + 1), size);
@@ -573,6 +573,7 @@ int check_erased_range(struct flashctx *flash, unsigned int start,
 int verify_range(struct flashctx *flash, uint8_t *cmpbuf, unsigned int start,
 		 unsigned int len, const char *message)
 {
+	const struct flashchip *chip = flash->chip;
 	unsigned int i;
 	uint8_t *readbuf = malloc(len);
 	int ret = 0, failcount = 0;
@@ -580,7 +581,7 @@ int verify_range(struct flashctx *flash, uint8_t *cmpbuf, unsigned int start,
 	if (!len)
 		goto out_free;
 
-	if (!flash->read) {
+	if (!chip->read) {
 		msg_cerr("ERROR: flashrom has no read function for this flash chip.\n");
 		return 1;
 	}
@@ -589,17 +590,17 @@ int verify_range(struct flashctx *flash, uint8_t *cmpbuf, unsigned int start,
 		exit(1);
 	}
 
-	if (start + len > flash->total_size * 1024) {
+	if (start + len > chip->total_size * 1024) {
 		msg_gerr("Error: %s called with start 0x%x + len 0x%x >"
 			" total_size 0x%x\n", __func__, start, len,
-			flash->total_size * 1024);
+			chip->total_size * 1024);
 		ret = -1;
 		goto out_free;
 	}
 	if (!message)
 		message = "VERIFY";
 
-	ret = flash->read(flash, readbuf, start, len);
+	ret = chip->read(flash, readbuf, start, len);
 	if (ret) {
 		msg_gerr("Verification impossible because read failed "
 			 "at 0x%x (len 0x%x)\n", start, len);
@@ -953,32 +954,38 @@ int check_max_decode(enum chipbustype buses, uint32_t size)
 int probe_flash(struct registered_programmer *pgm, int startchip,
 		struct flashctx *fill_flash, int force)
 {
-	const struct flashchip *flash;
+	const struct flashchip *chip;
 	unsigned long base = 0;
 	char location[64];
 	uint32_t size;
 	enum chipbustype buses_common;
 	char *tmp;
 
-	for (flash = flashchips + startchip; flash && flash->name; flash++) {
-		if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0)
+	for (chip = flashchips + startchip; chip && chip->name; chip++) {
+		if (chip_to_probe && strcmp(chip->name, chip_to_probe) != 0)
 			continue;
-		buses_common = pgm->buses_supported & flash->bustype;
+		buses_common = pgm->buses_supported & chip->bustype;
 		if (!buses_common)
 			continue;
 		msg_gdbg("Probing for %s %s, %d kB: ",
-			     flash->vendor, flash->name, flash->total_size);
-		if (!flash->probe && !force) {
+			     chip->vendor, chip->name, chip->total_size);
+		if (!chip->probe && !force) {
 			msg_gdbg("failed! flashrom has no probe function for "
 				 "this flash chip.\n");
 			continue;
 		}
 
-		size = flash->total_size * 1024;
+		size = chip->total_size * 1024;
 		check_max_decode(buses_common, size);
 
 		/* Start filling in the dynamic data. */
-		memcpy(fill_flash, flash, sizeof(struct flashchip));
+		/* FIXME: when to free? */
+		fill_flash->chip = malloc(sizeof(struct flashchip));
+		if (fill_flash->chip == NULL) {
+			msg_gerr("%s: out of memory.\n", __func__);
+			return -1;
+		}
+		memcpy(fill_flash->chip, chip, sizeof(struct flashchip));
 		fill_flash->pgm = pgm;
 
 		base = flashbase ? flashbase : (0xffffffff - size + 1);
@@ -987,7 +994,7 @@ int probe_flash(struct registered_programmer *pgm, int startchip,
 		if (force)
 			break;
 
-		if (fill_flash->probe(fill_flash) != 1)
+		if (chip->probe(fill_flash) != 1)
 			goto notfound;
 
 		/* If this is the first chip found, accept it.
@@ -997,7 +1004,7 @@ int probe_flash(struct registered_programmer *pgm, int startchip,
 		 * one for this programmer interface and thus no other chip has
 		 * been found on this interface.
 		 */
-		if (startchip == 0 && fill_flash->model_id == SFDP_DEVICE_ID) {
+		if (startchip == 0 && chip->model_id == SFDP_DEVICE_ID) {
 			msg_cinfo("===\n"
 				  "SFDP has autodetected a flash chip which is "
 				  "not natively supported by flashrom yet.\n");
@@ -1022,16 +1029,17 @@ int probe_flash(struct registered_programmer *pgm, int startchip,
 		}
 
 		if (startchip == 0 ||
-		    ((fill_flash->model_id != GENERIC_DEVICE_ID) &&
-		     (fill_flash->model_id != SFDP_DEVICE_ID)))
+		    ((chip->model_id != GENERIC_DEVICE_ID) && (chip->model_id != SFDP_DEVICE_ID)))
 			break;
 
 notfound:
 		programmer_unmap_flash_region((void *)fill_flash->virtual_memory, size);
 	}
 
-	if (!flash || !flash->name)
+	if (!chip || !chip->name) {
+		free(fill_flash->chip);
 		return -1;
+	}
 
 #if CONFIG_INTERNAL == 1
 	if (programmer_table[programmer].map_flash_region == physmap)
@@ -1040,27 +1048,27 @@ notfound:
 #endif
 		snprintf(location, sizeof(location), "on %s", programmer_table[programmer].name);
 
-	tmp = flashbuses_to_text(flash->bustype);
+	tmp = flashbuses_to_text(chip->bustype);
 	msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) %s.\n",
-		  force ? "Assuming" : "Found", fill_flash->vendor,
-		  fill_flash->name, fill_flash->total_size, tmp, location);
+		  force ? "Assuming" : "Found", chip->vendor,
+		  chip->name, chip->total_size, tmp, location);
 	free(tmp);
 
 	/* Flash registers will not be mapped if the chip was forced. Lock info
 	 * may be stored in registers, so avoid lock info printing.
 	 */
 	if (!force)
-		if (fill_flash->printlock)
-			fill_flash->printlock(fill_flash);
+		if (chip->printlock)
+			chip->printlock(fill_flash);
 
 	/* Return position of matching chip. */
-	return flash - flashchips;
+	return chip - flashchips;
 }
 
 int verify_flash(struct flashctx *flash, uint8_t *buf)
 {
 	int ret;
-	unsigned int total_size = flash->total_size * 1024;
+	unsigned int total_size = flash->chip->total_size * 1024;
 
 	msg_cinfo("Verifying flash... ");
 
@@ -1133,7 +1141,7 @@ int write_buf_to_file(unsigned char *buf, unsigned long size,
 
 int read_flash_to_file(struct flashctx *flash, const char *filename)
 {
-	unsigned long size = flash->total_size * 1024;
+	unsigned long size = flash->chip->total_size * 1024;
 	unsigned char *buf = calloc(size, sizeof(char));
 	int ret = 0;
 
@@ -1143,12 +1151,12 @@ int read_flash_to_file(struct flashctx *flash, const char *filename)
 		msg_cinfo("FAILED.\n");
 		return 1;
 	}
-	if (!flash->read) {
+	if (!flash->chip->read) {
 		msg_cerr("No read function available for this flash chip.\n");
 		ret = 1;
 		goto out_free;
 	}
-	if (flash->read(flash, buf, 0, size)) {
+	if (flash->chip->read(flash, buf, 0, size)) {
 		msg_cerr("Read operation failed!\n");
 		ret = 1;
 		goto out_free;
@@ -1165,14 +1173,14 @@ out_free:
  * walk_eraseregions().
  * Even if an error is found, the function will keep going and check the rest.
  */
-static int selfcheck_eraseblocks(const struct flashchip *flash)
+static int selfcheck_eraseblocks(const struct flashchip *chip)
 {
 	int i, j, k;
 	int ret = 0;
 
 	for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
 		unsigned int done = 0;
-		struct block_eraser eraser = flash->block_erasers[k];
+		struct block_eraser eraser = chip->block_erasers[k];
 
 		for (i = 0; i < NUM_ERASEREGIONS; i++) {
 			/* Blocks with zero size are bugs in flashchips.c. */
@@ -1181,7 +1189,7 @@ static int selfcheck_eraseblocks(const struct flashchip *flash)
 				msg_gerr("ERROR: Flash chip %s erase function "
 					"%i region %i has size 0. Please report"
 					" a bug at flashrom@flashrom.org\n",
-					flash->name, k, i);
+					chip->name, k, i);
 				ret = 1;
 			}
 			/* Blocks with zero count are bugs in flashchips.c. */
@@ -1190,7 +1198,7 @@ static int selfcheck_eraseblocks(const struct flashchip *flash)
 				msg_gerr("ERROR: Flash chip %s erase function "
 					"%i region %i has count 0. Please report"
 					" a bug at flashrom@flashrom.org\n",
-					flash->name, k, i);
+					chip->name, k, i);
 				ret = 1;
 			}
 			done += eraser.eraseblocks[i].count *
@@ -1202,12 +1210,12 @@ static int selfcheck_eraseblocks(const struct flashchip *flash)
 				  "non-empty erase function. Not an error.\n");
 		if (!done)
 			continue;
-		if (done != flash->total_size * 1024) {
+		if (done != chip->total_size * 1024) {
 			msg_gerr("ERROR: Flash chip %s erase function %i "
 				"region walking resulted in 0x%06x bytes total,"
 				" expected 0x%06x bytes. Please report a bug at"
-				" flashrom@flashrom.org\n", flash->name, k,
-				done, flash->total_size * 1024);
+				" flashrom@flashrom.org\n", chip->name, k,
+				done, chip->total_size * 1024);
 			ret = 1;
 		}
 		if (!eraser.block_erase)
@@ -1218,11 +1226,11 @@ static int selfcheck_eraseblocks(const struct flashchip *flash)
 		 */
 		for (j = k + 1; j < NUM_ERASEFUNCTIONS; j++) {
 			if (eraser.block_erase ==
-			    flash->block_erasers[j].block_erase) {
+			    chip->block_erasers[j].block_erase) {
 				msg_gerr("ERROR: Flash chip %s erase function "
 					"%i and %i are identical. Please report"
 					" a bug at flashrom@flashrom.org\n",
-					flash->name, k, j);
+					chip->name, k, j);
 				ret = 1;
 			}
 		}
@@ -1269,7 +1277,7 @@ static int erase_and_write_block_helper(struct flashctx *flash,
 		if (!writecount++)
 			msg_cdbg("W");
 		/* Needs the partial write function signature. */
-		ret = flash->write(flash, newcontents + starthere,
+		ret = flash->chip->write(flash, newcontents + starthere,
 				   start + starthere, lenhere);
 		if (ret)
 			return ret;
@@ -1296,7 +1304,7 @@ static int walk_eraseregions(struct flashctx *flash, int erasefunction,
 	int i, j;
 	unsigned int start = 0;
 	unsigned int len;
-	struct block_eraser eraser = flash->block_erasers[erasefunction];
+	struct block_eraser eraser = flash->chip->block_erasers[erasefunction];
 
 	for (i = 0; i < NUM_ERASEREGIONS; i++) {
 		/* count==0 for all automatically initialized array
@@ -1322,7 +1330,7 @@ static int walk_eraseregions(struct flashctx *flash, int erasefunction,
 
 static int check_block_eraser(const struct flashctx *flash, int k, int log)
 {
-	struct block_eraser eraser = flash->block_erasers[k];
+	struct block_eraser eraser = flash->chip->block_erasers[k];
 
 	if (!eraser.block_erase && !eraser.eraseblocks[0].count) {
 		if (log)
@@ -1347,10 +1355,12 @@ static int check_block_eraser(const struct flashctx *flash, int k, int log)
 int erase_and_write_flash(struct flashctx *flash, uint8_t *oldcontents,
 			  uint8_t *newcontents)
 {
-	int k, ret = 1;
-	uint8_t *curcontents;
-	unsigned long size = flash->total_size * 1024;
+	int ret = 1;
+	const struct flashchip *chip = flash->chip;
+	unsigned long size = chip->total_size * 1024;
 	unsigned int usable_erasefunctions = count_usable_erasers(flash);
+	int k;
+	uint8_t *curcontents;
 
 	msg_cinfo("Erasing and writing flash chip... ");
 	curcontents = malloc(size);
@@ -1387,7 +1397,7 @@ int erase_and_write_flash(struct flashctx *flash, uint8_t *oldcontents,
 		 * in non-verbose mode.
 		 */
 		msg_cinfo("Reading current flash chip contents... ");
-		if (flash->read(flash, curcontents, 0, size)) {
+		if (chip->read(flash, curcontents, 0, size)) {
 			/* Now we are truly screwed. Read failed as well. */
 			msg_cerr("Can't read anymore! Aborting.\n");
 			/* We have no idea about the flash chip contents, so
@@ -1576,7 +1586,7 @@ void print_banner(void)
 int selfcheck(void)
 {
 	int ret = 0;
-	const struct flashchip *flash;
+	const struct flashchip *chip;
 
 	/* Safety check. Instead of aborting after the first error, check
 	 * if more errors exist.
@@ -1594,16 +1604,8 @@ int selfcheck(void)
 		msg_gerr("Flashchips table miscompilation!\n");
 		ret = 1;
 	}
-	/* Check that virtual_memory in struct flashctx is placed directly
-	 * after the members copied from struct flashchip.
-	 */
-	if (sizeof(struct flashchip) !=
-	    offsetof(struct flashctx, virtual_memory)) {
-		msg_gerr("struct flashctx broken!\n");
-		ret = 1;
-	}
-	for (flash = flashchips; flash && flash->name; flash++)
-		if (selfcheck_eraseblocks(flash))
+	for (chip = flashchips; chip && chip->name; chip++)
+		if (selfcheck_eraseblocks(chip))
 			ret = 1;
 
 #if CONFIG_INTERNAL == 1
@@ -1627,41 +1629,41 @@ int selfcheck(void)
 	return ret;
 }
 
-void check_chip_supported(const struct flashctx *flash)
+void check_chip_supported(const struct flashchip *chip)
 {
-	if (flash->feature_bits & FEATURE_OTP) {
+	if (chip->feature_bits & FEATURE_OTP) {
 		msg_cdbg("This chip may contain one-time programmable memory. "
 			 "flashrom cannot read\nand may never be able to write "
 			 "it, hence it may not be able to completely\n"
 			 "clone the contents of this chip (see man page for "
 			 "details).\n");
 	}
-	if (TEST_OK_MASK != (flash->tested & TEST_OK_MASK)) {
+	if (TEST_OK_MASK != (chip->tested & TEST_OK_MASK)) {
 		msg_cinfo("===\n");
-		if (flash->tested & TEST_BAD_MASK) {
+		if (chip->tested & TEST_BAD_MASK) {
 			msg_cinfo("This flash part has status NOT WORKING for operations:");
-			if (flash->tested & TEST_BAD_PROBE)
+			if (chip->tested & TEST_BAD_PROBE)
 				msg_cinfo(" PROBE");
-			if (flash->tested & TEST_BAD_READ)
+			if (chip->tested & TEST_BAD_READ)
 				msg_cinfo(" READ");
-			if (flash->tested & TEST_BAD_ERASE)
+			if (chip->tested & TEST_BAD_ERASE)
 				msg_cinfo(" ERASE");
-			if (flash->tested & TEST_BAD_WRITE)
+			if (chip->tested & TEST_BAD_WRITE)
 				msg_cinfo(" WRITE");
 			msg_cinfo("\n");
 		}
-		if ((!(flash->tested & TEST_BAD_PROBE) && !(flash->tested & TEST_OK_PROBE)) ||
-		    (!(flash->tested & TEST_BAD_READ) && !(flash->tested & TEST_OK_READ)) ||
-		    (!(flash->tested & TEST_BAD_ERASE) && !(flash->tested & TEST_OK_ERASE)) ||
-		    (!(flash->tested & TEST_BAD_WRITE) && !(flash->tested & TEST_OK_WRITE))) {
+		if ((!(chip->tested & TEST_BAD_PROBE) && !(chip->tested & TEST_OK_PROBE)) ||
+		    (!(chip->tested & TEST_BAD_READ) && !(chip->tested & TEST_OK_READ)) ||
+		    (!(chip->tested & TEST_BAD_ERASE) && !(chip->tested & TEST_OK_ERASE)) ||
+		    (!(chip->tested & TEST_BAD_WRITE) && !(chip->tested & TEST_OK_WRITE))) {
 			msg_cinfo("This flash part has status UNTESTED for operations:");
-			if (!(flash->tested & TEST_BAD_PROBE) && !(flash->tested & TEST_OK_PROBE))
+			if (!(chip->tested & TEST_BAD_PROBE) && !(chip->tested & TEST_OK_PROBE))
 				msg_cinfo(" PROBE");
-			if (!(flash->tested & TEST_BAD_READ) && !(flash->tested & TEST_OK_READ))
+			if (!(chip->tested & TEST_BAD_READ) && !(chip->tested & TEST_OK_READ))
 				msg_cinfo(" READ");
-			if (!(flash->tested & TEST_BAD_ERASE) && !(flash->tested & TEST_OK_ERASE))
+			if (!(chip->tested & TEST_BAD_ERASE) && !(chip->tested & TEST_OK_ERASE))
 				msg_cinfo(" ERASE");
-			if (!(flash->tested & TEST_BAD_WRITE) && !(flash->tested & TEST_OK_WRITE))
+			if (!(chip->tested & TEST_BAD_WRITE) && !(chip->tested & TEST_OK_WRITE))
 				msg_cinfo(" WRITE");
 			msg_cinfo("\n");
 		}
@@ -1686,9 +1688,10 @@ void check_chip_supported(const struct flashctx *flash)
 /* FIXME: This function signature needs to be improved once doit() has a better
  * function signature.
  */
-int chip_safety_check(struct flashctx *flash, int force, int read_it,
+int chip_safety_check(const struct flashctx *flash, int force, int read_it,
 		      int write_it, int erase_it, int verify_it)
 {
+	const struct flashchip *chip = flash->chip;
 	if (!programmer_may_write && (write_it || erase_it)) {
 		msg_perr("Write/erase is not working yet on your programmer in "
 			 "its current configuration.\n");
@@ -1702,13 +1705,13 @@ int chip_safety_check(struct flashctx *flash, int force, int read_it,
 
 	if (read_it || erase_it || write_it || verify_it) {
 		/* Everything needs read. */
-		if (flash->tested & TEST_BAD_READ) {
+		if (chip->tested & TEST_BAD_READ) {
 			msg_cerr("Read is not working on this chip. ");
 			if (!force)
 				return 1;
 			msg_cerr("Continuing anyway.\n");
 		}
-		if (!flash->read) {
+		if (!chip->read) {
 			msg_cerr("flashrom has no read function for this "
 				 "flash chip.\n");
 			return 1;
@@ -1716,7 +1719,7 @@ int chip_safety_check(struct flashctx *flash, int force, int read_it,
 	}
 	if (erase_it || write_it) {
 		/* Write needs erase. */
-		if (flash->tested & TEST_BAD_ERASE) {
+		if (chip->tested & TEST_BAD_ERASE) {
 			msg_cerr("Erase is not working on this chip. ");
 			if (!force)
 				return 1;
@@ -1729,13 +1732,13 @@ int chip_safety_check(struct flashctx *flash, int force, int read_it,
 		}
 	}
 	if (write_it) {
-		if (flash->tested & TEST_BAD_WRITE) {
+		if (chip->tested & TEST_BAD_WRITE) {
 			msg_cerr("Write is not working on this chip. ");
 			if (!force)
 				return 1;
 			msg_cerr("Continuing anyway.\n");
 		}
-		if (!flash->write) {
+		if (!chip->write) {
 			msg_cerr("flashrom has no write function for this "
 				 "flash chip.\n");
 			return 1;
@@ -1754,7 +1757,8 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 	uint8_t *oldcontents;
 	uint8_t *newcontents;
 	int ret = 0;
-	unsigned long size = flash->total_size * 1024;
+	const struct flashchip *chip = flash->chip;
+	unsigned long size = chip->total_size * 1024;
 
 	if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) {
 		msg_cerr("Aborting.\n");
@@ -1765,8 +1769,8 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 	/* Given the existence of read locks, we want to unlock for read,
 	 * erase and write.
 	 */
-	if (flash->unlock)
-		flash->unlock(flash);
+	if (chip->unlock)
+		chip->unlock(flash);
 
 	if (read_it) {
 		ret = read_flash_to_file(flash, filename);
@@ -1829,7 +1833,7 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 	 * takes time as well.
 	 */
 	msg_cinfo("Reading old flash chip contents... ");
-	if (flash->read(flash, oldcontents, 0, size)) {
+	if (chip->read(flash, oldcontents, 0, size)) {
 		ret = 1;
 		msg_cinfo("FAILED.\n");
 		goto out;
@@ -1846,7 +1850,7 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 		if (erase_and_write_flash(flash, oldcontents, newcontents)) {
 			msg_cerr("Uh oh. Erase/write failed. Checking if "
 				 "anything changed.\n");
-			if (!flash->read(flash, newcontents, 0, size)) {
+			if (!chip->read(flash, newcontents, 0, size)) {
 				if (!memcmp(oldcontents, newcontents, size)) {
 					msg_cinfo("Good. It seems nothing was "
 						  "changed.\n");
diff --git a/ichspi.c b/ichspi.c
index 0223ae3..b2d4fbb 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1193,9 +1193,9 @@ static int ich_hwseq_probe(struct flashctx *flash)
 	else
 		msg_cdbg(" with a");
 	msg_cdbg(" density of %d kB.\n", total_size / 1024);
-	flash->total_size = total_size / 1024;
+	flash->chip->total_size = total_size / 1024;
 
-	eraser = &(flash->block_erasers[0]);
+	eraser = &(flash->chip->block_erasers[0]);
 	boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
 	size_high = total_size - boundary;
 	erase_size_high = ich_hwseq_get_erase_block_size(boundary);
@@ -1228,7 +1228,7 @@ static int ich_hwseq_probe(struct flashctx *flash)
 		msg_cdbg("In that range are %d erase blocks with %d B each.\n",
 			 size_high / erase_size_high, erase_size_high);
 	}
-	flash->tested = TEST_OK_PREW;
+	flash->chip->tested = TEST_OK_PREW;
 	return 1;
 }
 
@@ -1256,7 +1256,7 @@ static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr,
 		return -1;
 	}
 
-	if (addr + len > flash->total_size * 1024) {
+	if (addr + len > flash->chip->total_size * 1024) {
 		msg_perr("Request to erase some inaccessible memory address(es)"
 			 " (addr=0x%x, len=%d). "
 			 "Not erasing anything.\n", addr, len);
@@ -1288,7 +1288,7 @@ static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf,
 	uint16_t timeout = 100 * 60;
 	uint8_t block_len;
 
-	if (addr + len > flash->total_size * 1024) {
+	if (addr + len > flash->chip->total_size * 1024) {
 		msg_perr("Request to read from an inaccessible memory address "
 			 "(addr=0x%x, len=%d).\n", addr, len);
 		return -1;
@@ -1326,7 +1326,7 @@ static int ich_hwseq_write(struct flashctx *flash, uint8_t *buf,
 	uint16_t timeout = 100 * 60;
 	uint8_t block_len;
 
-	if (addr + len > flash->total_size * 1024) {
+	if (addr + len > flash->chip->total_size * 1024) {
 		msg_perr("Request to write to an inaccessible memory address "
 			 "(addr=0x%x, len=%d).\n", addr, len);
 		return -1;
diff --git a/it87spi.c b/it87spi.c
index c7bbb13..fb2f794 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -331,7 +331,7 @@ static int it8716f_spi_page_program(struct flashctx *flash, uint8_t *buf,
 	/* FIXME: The command below seems to be redundant or wrong. */
 	OUTB(0x06, it8716f_flashport + 1);
 	OUTB(((2 + (fast_spi ? 1 : 0)) << 4), it8716f_flashport);
-	for (i = 0; i < flash->page_size; i++)
+	for (i = 0; i < flash->chip->page_size; i++)
 		mmio_writeb(buf[i], (void *)(bios + start + i));
 	OUTB(0, it8716f_flashport);
 	/* Wait until the Write-In-Progress bit is cleared.
@@ -355,7 +355,7 @@ static int it8716f_spi_chip_read(struct flashctx *flash, uint8_t *buf,
 	 * the mainboard does not use IT87 SPI translation. This should be done
 	 * via a programmer parameter for the internal programmer.
 	 */
-	if ((flash->total_size * 1024 > 512 * 1024)) {
+	if ((flash->chip->total_size * 1024 > 512 * 1024)) {
 		spi_read_chunked(flash, buf, start, len, 3);
 	} else {
 		mmio_readn((void *)(flash->virtual_memory + start), buf, len);
@@ -367,6 +367,7 @@ static int it8716f_spi_chip_read(struct flashctx *flash, uint8_t *buf,
 static int it8716f_spi_chip_write_256(struct flashctx *flash, uint8_t *buf,
 				      unsigned int start, unsigned int len)
 {
+	const struct flashchip *chip = flash->chip;
 	/*
 	 * IT8716F only allows maximum of 512 kb SPI chip size for memory
 	 * mapped access. It also can't write more than 1+3+256 bytes at once,
@@ -377,28 +378,27 @@ static int it8716f_spi_chip_write_256(struct flashctx *flash, uint8_t *buf,
 	 * the mainboard does not use IT87 SPI translation. This should be done
 	 * via a programmer parameter for the internal programmer.
 	 */
-	if ((flash->total_size * 1024 > 512 * 1024) ||
-	    (flash->page_size > 256)) {
+	if ((chip->total_size * 1024 > 512 * 1024) || (chip->page_size > 256)) {
 		spi_chip_write_1(flash, buf, start, len);
 	} else {
 		unsigned int lenhere;
 
-		if (start % flash->page_size) {
+		if (start % chip->page_size) {
 			/* start to the end of the page or to start + len,
 			 * whichever is smaller.
 			 */
-			lenhere = min(len, flash->page_size - start % flash->page_size);
+			lenhere = min(len, chip->page_size - start % chip->page_size);
 			spi_chip_write_1(flash, buf, start, lenhere);
 			start += lenhere;
 			len -= lenhere;
 			buf += lenhere;
 		}
 
-		while (len >= flash->page_size) {
+		while (len >= chip->page_size) {
 			it8716f_spi_page_program(flash, buf, start);
-			start += flash->page_size;
-			len -= flash->page_size;
-			buf += flash->page_size;
+			start += chip->page_size;
+			len -= chip->page_size;
+			buf += chip->page_size;
 		}
 		if (len)
 			spi_chip_write_1(flash, buf, start, len);
diff --git a/jedec.c b/jedec.c
index 69c0c0c..d8532c6 100644
--- a/jedec.c
+++ b/jedec.c
@@ -93,9 +93,9 @@ void data_polling_jedec(const struct flashctx *flash, chipaddr dst,
 		msg_cdbg("%s: excessive loops, i=0x%x\n", __func__, i);
 }
 
-static unsigned int getaddrmask(struct flashctx *flash)
+static unsigned int getaddrmask(const struct flashchip *chip)
 {
-	switch (flash->feature_bits & FEATURE_ADDR_MASK) {
+	switch (chip->feature_bits & FEATURE_ADDR_MASK) {
 	case FEATURE_ADDR_FULL:
 		return MASK_FULL;
 		break;
@@ -124,16 +124,17 @@ static void start_program_jedec_common(struct flashctx *flash,
 static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
+	const struct flashchip *chip = flash->chip;
 	uint8_t id1, id2;
 	uint32_t largeid1, largeid2;
 	uint32_t flashcontent1, flashcontent2;
 	int probe_timing_enter, probe_timing_exit;
 
-	if (flash->probe_timing > 0) 
-		probe_timing_enter = probe_timing_exit = flash->probe_timing;
-	else if (flash->probe_timing == TIMING_ZERO) { /* No delay. */
+	if (chip->probe_timing > 0)
+		probe_timing_enter = probe_timing_exit = chip->probe_timing;
+	else if (chip->probe_timing == TIMING_ZERO) { /* No delay. */
 		probe_timing_enter = probe_timing_exit = 0;
-	} else if (flash->probe_timing == TIMING_FIXME) { /* == _IGNORED */
+	} else if (chip->probe_timing == TIMING_FIXME) { /* == _IGNORED */
 		msg_cdbg("Chip lacks correct probe timing information, "
 			     "using default 10mS/40uS. ");
 		probe_timing_enter = 10000;
@@ -151,7 +152,7 @@ static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 	if (probe_timing_enter)
 		programmer_delay(probe_timing_enter);
 	/* Reset chip to a clean slate */
-	if ((flash->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
+	if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
 	{
 		chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 		if (probe_timing_exit)
@@ -194,7 +195,7 @@ static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 	}
 
 	/* Issue JEDEC Product ID Exit command */
-	if ((flash->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
+	if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
 	{
 		chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
 		if (probe_timing_exit)
@@ -231,10 +232,10 @@ static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 		msg_cdbg(", id2 is normal flash content");
 
 	msg_cdbg("\n");
-	if (largeid1 != flash->manufacture_id || largeid2 != flash->model_id)
+	if (largeid1 != chip->manufacture_id || largeid2 != chip->model_id)
 		return 0;
 
-	if (flash->feature_bits & FEATURE_REGISTERMAP)
+	if (chip->feature_bits & FEATURE_REGISTERMAP)
 		map_flash_registers(flash);
 
 	return 1;
@@ -245,7 +246,7 @@ static int erase_sector_jedec_common(struct flashctx *flash, unsigned int page,
 {
 	chipaddr bios = flash->virtual_memory;
 	int delay_us = 0;
-	if(flash->probe_timing != TIMING_ZERO)
+	if(flash->chip->probe_timing != TIMING_ZERO)
 	        delay_us = 10;
 
 	/*  Issue the Sector Erase command   */
@@ -275,7 +276,7 @@ static int erase_block_jedec_common(struct flashctx *flash, unsigned int block,
 {
 	chipaddr bios = flash->virtual_memory;
 	int delay_us = 0;
-	if(flash->probe_timing != TIMING_ZERO)
+	if(flash->chip->probe_timing != TIMING_ZERO)
 	        delay_us = 10;
 
 	/*  Issue the Sector Erase command   */
@@ -304,7 +305,7 @@ static int erase_chip_jedec_common(struct flashctx *flash, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
 	int delay_us = 0;
-	if(flash->probe_timing != TIMING_ZERO)
+	if(flash->chip->probe_timing != TIMING_ZERO)
 	        delay_us = 10;
 
 	/*  Issue the JEDEC Chip Erase command   */
@@ -366,7 +367,7 @@ int write_jedec_1(struct flashctx *flash, uint8_t *src, unsigned int start,
 	chipaddr olddst;
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
+	mask = getaddrmask(flash->chip);
 
 	olddst = dst;
 	for (i = 0; i < len; i++) {
@@ -390,7 +391,7 @@ int write_page_write_jedec_common(struct flashctx *flash, uint8_t *src,
 	chipaddr d = dst;
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
+	mask = getaddrmask(flash->chip);
 
 retry:
 	/* Issue JEDEC Start Program command */
@@ -438,7 +439,7 @@ int write_jedec(struct flashctx *flash, uint8_t *buf, unsigned int start,
 	 * write_jedec have page_size set to max_writechunk_size, so
 	 * we're OK for now.
 	 */
-	unsigned int page_size = flash->page_size;
+	unsigned int page_size = flash->chip->page_size;
 
 	/* Warning: This loop has a very unusual condition and body.
 	 * The loop needs to go through each page with at least one affected
@@ -469,8 +470,8 @@ int erase_chip_block_jedec(struct flashctx *flash, unsigned int addr,
 {
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
-	if ((addr != 0) || (blocksize != flash->total_size * 1024)) {
+	mask = getaddrmask(flash->chip);
+	if ((addr != 0) || (blocksize != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n",
 			__func__);
 		return -1;
@@ -482,7 +483,7 @@ int probe_jedec(struct flashctx *flash)
 {
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
+	mask = getaddrmask(flash->chip);
 	return probe_jedec_common(flash, mask);
 }
 
@@ -491,7 +492,7 @@ int erase_sector_jedec(struct flashctx *flash, unsigned int page,
 {
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
+	mask = getaddrmask(flash->chip);
 	return erase_sector_jedec_common(flash, page, size, mask);
 }
 
@@ -500,7 +501,7 @@ int erase_block_jedec(struct flashctx *flash, unsigned int page,
 {
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
+	mask = getaddrmask(flash->chip);
 	return erase_block_jedec_common(flash, page, size, mask);
 }
 
@@ -508,6 +509,6 @@ int erase_chip_jedec(struct flashctx *flash)
 {
 	unsigned int mask;
 
-	mask = getaddrmask(flash);
+	mask = getaddrmask(flash->chip);
 	return erase_chip_jedec_common(flash, mask);
 }
diff --git a/layout.c b/layout.c
index 8663402..2348f8a 100644
--- a/layout.c
+++ b/layout.c
@@ -217,11 +217,11 @@ romlayout_t *get_next_included_romentry(unsigned int start)
 	return best_entry;
 }
 
-int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents)
+int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents)
 {
 	unsigned int start = 0;
 	romlayout_t *entry;
-	unsigned int size = flash->total_size * 1024;
+	unsigned int size = flash->chip->total_size * 1024;
 
 	/* If no regions were specified for inclusion, assume
 	 * that the user wants to write the complete new image.
diff --git a/m29f400bt.c b/m29f400bt.c
index c9d8a40..8f0329e 100644
--- a/m29f400bt.c
+++ b/m29f400bt.c
@@ -81,7 +81,7 @@ int probe_m29f400bt(struct flashctx *flash)
 
 	msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
 
-	if (id1 == flash->manufacture_id && id2 == flash->model_id)
+	if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id)
 		return 1;
 
 	return 0;
@@ -130,7 +130,7 @@ int block_erase_m29f400bt(struct flashctx *flash, unsigned int start,
 int block_erase_chip_m29f400bt(struct flashctx *flash, unsigned int address,
 			       unsigned int blocklen)
 {
-	if ((address != 0) || (blocklen != flash->total_size * 1024)) {
+	if ((address != 0) || (blocklen != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n",
 			__func__);
 		return -1;
diff --git a/pm49fl00x.c b/pm49fl00x.c
index 42db2aa..fe28d2b 100644
--- a/pm49fl00x.c
+++ b/pm49fl00x.c
@@ -40,14 +40,14 @@ static void write_lockbits_49fl00x(const struct flashctx *flash,
 
 int unlock_49fl00x(struct flashctx *flash)
 {
-	write_lockbits_49fl00x(flash, flash->total_size * 1024, 0,
-			       flash->page_size);
+	write_lockbits_49fl00x(flash, flash->chip->total_size * 1024, 0,
+			       flash->chip->page_size);
 	return 0;
 }
 
 int lock_49fl00x(struct flashctx *flash)
 {
-	write_lockbits_49fl00x(flash, flash->total_size * 1024, 1,
-			       flash->page_size);
+	write_lockbits_49fl00x(flash, flash->chip->total_size * 1024, 1,
+			       flash->chip->page_size);
 	return 0;
 }
diff --git a/print.c b/print.c
index 5a2f902..fc885d4 100644
--- a/print.c
+++ b/print.c
@@ -67,22 +67,22 @@ static void print_supported_chips(void)
 	int maxvendorlen = strlen("Vendor") + 1;
 	int maxchiplen = strlen("Device") + 1;
 	int maxtypelen = strlen("Type") + 1;
-	const struct flashchip *f;
+	const struct flashchip *chip;
 	char *s;
 	char *tmpven, *tmpdev;
 	int tmpvenlen, tmpdevlen, curvenlen, curdevlen;
 
 	/* calculate maximum column widths and by iterating over all chips */
-	for (f = flashchips; f->name != NULL; f++) {
+	for (chip = flashchips; chip->name != NULL; chip++) {
 		/* Ignore generic entries. */
-		if (!strncmp(f->vendor, "Unknown", 7) ||
-		    !strncmp(f->vendor, "Programmer", 10) ||
-		    !strncmp(f->name, "unknown", 7))
+		if (!strncmp(chip->vendor, "Unknown", 7) ||
+		    !strncmp(chip->vendor, "Programmer", 10) ||
+		    !strncmp(chip->name, "unknown", 7))
 			continue;
 		chipcount++;
 
 		/* Find maximum vendor length (respecting line splitting). */
-		tmpven = (char *)f->vendor;
+		tmpven = (char *)chip->vendor;
 		do {
 			/* and take minimum token lengths into account */
 			tmpvenlen = 0;
@@ -100,7 +100,7 @@ static void print_supported_chips(void)
 		} while (1);
 
 		/* same for device name */
-		tmpdev = (char *)f->name;
+		tmpdev = (char *)chip->name;
 		do {
 			tmpdevlen = 0;
 			do {
@@ -115,7 +115,7 @@ static void print_supported_chips(void)
 				break;
 		} while (1);
 
-		s = flashbuses_to_text(f->bustype);
+		s = flashbuses_to_text(chip->bustype);
 		maxtypelen = max(maxtypelen, strlen(s));
 		free(s);
 	}
@@ -162,11 +162,11 @@ static void print_supported_chips(void)
 	msg_ginfo("\n\n");
 	msg_ginfo("(P = PROBE, R = READ, E = ERASE, W = WRITE)\n\n");
 
-	for (f = flashchips; f->name != NULL; f++) {
+	for (chip = flashchips; chip->name != NULL; chip++) {
 		/* Don't print generic entries. */
-		if (!strncmp(f->vendor, "Unknown", 7) ||
-		    !strncmp(f->vendor, "Programmer", 10) ||
-		    !strncmp(f->name, "unknown", 7))
+		if (!strncmp(chip->vendor, "Unknown", 7) ||
+		    !strncmp(chip->vendor, "Programmer", 10) ||
+		    !strncmp(chip->name, "unknown", 7))
 			continue;
 
 		/* support for multiline vendor names:
@@ -179,12 +179,12 @@ static void print_supported_chips(void)
 		 * - after all other values are printed print the surplus tokens
 		 *   on fresh lines
 		 */
-		tmpven = malloc(strlen(f->vendor) + 1);
+		tmpven = malloc(strlen(chip->vendor) + 1);
 		if (tmpven == NULL) {
 			msg_gerr("Out of memory!\n");
 			exit(1);
 		}
-		strcpy(tmpven, f->vendor);
+		strcpy(tmpven, chip->vendor);
 
 		tmpven = strtok(tmpven, delim);
 		msg_ginfo("%s", tmpven);
@@ -203,12 +203,12 @@ static void print_supported_chips(void)
 			msg_ginfo(" ");
 
 		/* support for multiline device names as above */
-		tmpdev = malloc(strlen(f->name) + 1);
+		tmpdev = malloc(strlen(chip->name) + 1);
 		if (tmpdev == NULL) {
 			msg_gerr("Out of memory!\n");
 			exit(1);
 		}
-		strcpy(tmpdev, f->name);
+		strcpy(tmpdev, chip->name);
 
 		tmpdev = strtok(tmpdev, delim);
 		msg_ginfo("%s", tmpdev);
@@ -226,60 +226,60 @@ static void print_supported_chips(void)
 		for (i = curdevlen; i < maxchiplen; i++)
 			msg_ginfo(" ");
 
-		if ((f->tested & TEST_OK_PROBE))
+		if ((chip->tested & TEST_OK_PROBE))
 			msg_ginfo("P");
 		else
 			msg_ginfo(" ");
-		if ((f->tested & TEST_OK_READ))
+		if ((chip->tested & TEST_OK_READ))
 			msg_ginfo("R");
 		else
 			msg_ginfo(" ");
-		if ((f->tested & TEST_OK_ERASE))
+		if ((chip->tested & TEST_OK_ERASE))
 			msg_ginfo("E");
 		else
 			msg_ginfo(" ");
-		if ((f->tested & TEST_OK_WRITE))
+		if ((chip->tested & TEST_OK_WRITE))
 			msg_ginfo("W");
 		else
 			msg_ginfo(" ");
 		for (i = 0; i < border; i++)
 			msg_ginfo(" ");
 
-		if ((f->tested & TEST_BAD_PROBE))
+		if ((chip->tested & TEST_BAD_PROBE))
 			msg_ginfo("P");
 		else
 			msg_ginfo(" ");
-		if ((f->tested & TEST_BAD_READ))
+		if ((chip->tested & TEST_BAD_READ))
 			msg_ginfo("R");
 		else
 			msg_ginfo(" ");
-		if ((f->tested & TEST_BAD_ERASE))
+		if ((chip->tested & TEST_BAD_ERASE))
 			msg_ginfo("E");
 		else
 			msg_ginfo(" ");
-		if ((f->tested & TEST_BAD_WRITE))
+		if ((chip->tested & TEST_BAD_WRITE))
 			msg_ginfo("W");
 		else
 			msg_ginfo(" ");
 		for (i = 0; i < border + 1; i++)
 			msg_ginfo(" ");
 
-		msg_ginfo("%5d", f->total_size);
+		msg_ginfo("%5d", chip->total_size);
 		for (i = 0; i < border; i++)
 			msg_ginfo(" ");
 
-		s = flashbuses_to_text(f->bustype);
+		s = flashbuses_to_text(chip->bustype);
 		msg_ginfo("%s", s);
 		for (i = strlen(s); i < maxtypelen; i++)
 			msg_ginfo(" ");
 		free(s);
 
-		if (f->voltage.min == 0 && f->voltage.max == 0)
+		if (chip->voltage.min == 0 && chip->voltage.max == 0)
 			msg_gdbg("no info");
 		else
 			msg_gdbg("%0.02f;%0.02f",
-				 f->voltage.min/(double)1000,
-				 f->voltage.max/(double)1000);
+				 chip->voltage.min/(double)1000,
+				 chip->voltage.max/(double)1000);
 
 		/* print surplus vendor and device name tokens */
 		while (tmpven != NULL || tmpdev != NULL) {
diff --git a/programmer.h b/programmer.h
index 7d06be3..66bb258 100644
--- a/programmer.h
+++ b/programmer.h
@@ -475,7 +475,7 @@ struct decode_sizes {
 extern struct decode_sizes max_rom_decode;
 extern int programmer_may_write;
 extern unsigned long flashbase;
-void check_chip_supported(const struct flashctx *flash);
+void check_chip_supported(const struct flashchip *chip);
 int check_max_decode(enum chipbustype buses, uint32_t size);
 char *extract_programmer_param(const char *param_name);
 
diff --git a/sfdp.c b/sfdp.c
index 708b66b..bc69dd0 100644
--- a/sfdp.c
+++ b/sfdp.c
@@ -81,10 +81,10 @@ struct sfdp_tbl_hdr {
 	uint32_t ptp; /* 24b pointer */
 };
 
-static int sfdp_add_uniform_eraser(struct flashctx *flash, uint8_t opcode, uint32_t block_size)
+static int sfdp_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint32_t block_size)
 {
 	int i;
-	uint32_t total_size = flash->total_size * 1024;
+	uint32_t total_size = chip->total_size * 1024;
 	erasefunc_t *erasefn = spi_get_erasefn_from_opcode(opcode);
 
 	if (erasefn == NULL || total_size == 0 || block_size == 0 ||
@@ -95,7 +95,7 @@ static int sfdp_add_uniform_eraser(struct flashctx *flash, uint8_t opcode, uint3
 	}
 
 	for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
-		struct block_eraser *eraser = &flash->block_erasers[i];
+		struct block_eraser *eraser = &chip->block_erasers[i];
 		/* Check for duplicates (including (some) non-uniform ones). */
 		if (eraser->eraseblocks[0].size == block_size &&
 		    eraser->block_erase == erasefn) {
@@ -125,7 +125,7 @@ static int sfdp_add_uniform_eraser(struct flashctx *flash, uint8_t opcode, uint3
 	return 1;
 }
 
-static int sfdp_fill_flash(struct flashctx *flash, uint8_t *buf, uint16_t len)
+static int sfdp_fill_flash(struct flashchip *chip, uint8_t *buf, uint16_t len)
 {
 	uint8_t opcode_4k_erase = 0xFF;
 	uint32_t tmp32;
@@ -170,28 +170,28 @@ static int sfdp_fill_flash(struct flashctx *flash, uint8_t *buf, uint16_t len)
 		msg_cdbg2("volatile and writes to the status register have to "
 			  "be enabled with ");
 		if (tmp32 & (1 << 4)) {
-			flash->feature_bits = FEATURE_WRSR_WREN;
+			chip->feature_bits = FEATURE_WRSR_WREN;
 			msg_cdbg2("WREN (0x06).\n");
 		} else {
-			flash->feature_bits = FEATURE_WRSR_EWSR;
+			chip->feature_bits = FEATURE_WRSR_EWSR;
 			msg_cdbg2("EWSR (0x50).\n");
 		}
 	} else {
 		msg_cdbg2("non-volatile and the standard does not allow "
 			  "vendors to tell us whether EWSR/WREN is needed for "
 			  "status register writes - assuming EWSR.\n");
-			flash->feature_bits = FEATURE_WRSR_EWSR;
+			chip->feature_bits = FEATURE_WRSR_EWSR;
 		}
 
 	msg_cdbg2("  Write chunk size is ");
 	if (tmp32 & (1 << 2)) {
 		msg_cdbg2("at least 64 B.\n");
-		flash->page_size = 64;
-		flash->write = spi_chip_write_256;
+		chip->page_size = 64;
+		chip->write = spi_chip_write_256;
 	} else {
 		msg_cdbg2("1 B only.\n");
-		flash->page_size = 256;
-		flash->write = spi_chip_write_1;
+		chip->page_size = 256;
+		chip->write = spi_chip_write_1;
 	}
 
 	if ((tmp32 & 0x3) == 0x1) {
@@ -212,8 +212,8 @@ static int sfdp_fill_flash(struct flashctx *flash, uint8_t *buf, uint16_t len)
 		return 1;
 	}
 	total_size = ((tmp32 & 0x7FFFFFFF) + 1) / 8;
-	flash->total_size = total_size / 1024;
-	msg_cdbg2("  Flash chip size is %d kB.\n", flash->total_size);
+	chip->total_size = total_size / 1024;
+	msg_cdbg2("  Flash chip size is %d kB.\n", chip->total_size);
 	if (total_size > (1 << 24)) {
 		msg_cdbg("Flash chip size is bigger than what 3-Byte addressing "
 			 "can access.\n");
@@ -221,7 +221,7 @@ static int sfdp_fill_flash(struct flashctx *flash, uint8_t *buf, uint16_t len)
 	}
 
 	if (opcode_4k_erase != 0xFF)
-		sfdp_add_uniform_eraser(flash, opcode_4k_erase, 4 * 1024);
+		sfdp_add_uniform_eraser(chip, opcode_4k_erase, 4 * 1024);
 
 	/* FIXME: double words 3-7 contain unused fast read information */
 
@@ -252,7 +252,7 @@ static int sfdp_fill_flash(struct flashctx *flash, uint8_t *buf, uint16_t len)
 		tmp8 = buf[(4 * 7) + (j * 2) + 1];
 		msg_cspew("   Erase Sector Type %d Opcode: 0x%02x\n", j + 1,
 			  tmp8);
-		sfdp_add_uniform_eraser(flash, tmp8, block_size);
+		sfdp_add_uniform_eraser(chip, tmp8, block_size);
 	}
 
 done:
@@ -381,7 +381,7 @@ int probe_spi_sfdp(struct flashctx *flash)
 				msg_cdbg("Length of the mandatory JEDEC SFDP "
 					 "parameter table is wrong (%d B), "
 					 "skipping it.\n", len);
-			} else if (sfdp_fill_flash(flash, tbuf, len) == 0)
+			} else if (sfdp_fill_flash(flash->chip, tbuf, len) == 0)
 				ret = 1;
 		}
 		free(tbuf);
diff --git a/spi.c b/spi.c
index 62e1430..732f4c5 100644
--- a/spi.c
+++ b/spi.c
@@ -111,16 +111,16 @@ int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
 	 * means 0xffffff, the highest unsigned 24bit number.
 	 */
 	addrbase = spi_get_valid_read_addr(flash);
-	if (addrbase + flash->total_size * 1024 > (1 << 24)) {
+	if (addrbase + flash->chip->total_size * 1024 > (1 << 24)) {
 		msg_perr("Flash chip size exceeds the allowed access window. ");
 		msg_perr("Read will probably fail.\n");
 		/* Try to get the best alignment subject to constraints. */
-		addrbase = (1 << 24) - flash->total_size * 1024;
+		addrbase = (1 << 24) - flash->chip->total_size * 1024;
 	}
 	/* Check if alignment is native (at least the largest power of two which
 	 * is a factor of the mapped size of the chip).
 	 */
-	if (ffs(flash->total_size * 1024) > (ffs(addrbase) ? : 33)) {
+	if (ffs(flash->chip->total_size * 1024) > (ffs(addrbase) ? : 33)) {
 		msg_perr("Flash chip is not aligned natively in the allowed "
 			 "access window.\n");
 		msg_perr("Read will probably return garbage.\n");
diff --git a/spi25.c b/spi25.c
index 900df9c..880eded 100644
--- a/spi25.c
+++ b/spi25.c
@@ -117,6 +117,7 @@ int spi_write_disable(struct flashctx *flash)
 
 static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
 {
+	const struct flashchip *chip = flash->chip;
 	unsigned char readarr[4];
 	uint32_t id1;
 	uint32_t id2;
@@ -147,7 +148,7 @@ static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
 
 	msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
 
-	if (id1 == flash->manufacture_id && id2 == flash->model_id) {
+	if (id1 == chip->manufacture_id && id2 == chip->model_id) {
 		/* Print the status register to tell the
 		 * user about possible write protection.
 		 */
@@ -157,13 +158,11 @@ static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
 	}
 
 	/* Test if this is a pure vendor match. */
-	if (id1 == flash->manufacture_id &&
-	    GENERIC_DEVICE_ID == flash->model_id)
+	if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id)
 		return 1;
 
 	/* Test if there is any vendor ID. */
-	if (GENERIC_MANUF_ID == flash->manufacture_id &&
-	    id1 != 0xff)
+	if (GENERIC_MANUF_ID == chip->manufacture_id && id1 != 0xff)
 		return 1;
 
 	return 0;
@@ -198,6 +197,7 @@ int probe_spi_rdid4(struct flashctx *flash)
 
 int probe_spi_rems(struct flashctx *flash)
 {
+	const struct flashchip *chip = flash->chip;
 	unsigned char readarr[JEDEC_REMS_INSIZE];
 	uint32_t id1, id2;
 
@@ -210,7 +210,7 @@ int probe_spi_rems(struct flashctx *flash)
 
 	msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
 
-	if (id1 == flash->manufacture_id && id2 == flash->model_id) {
+	if (id1 == chip->manufacture_id && id2 == chip->model_id) {
 		/* Print the status register to tell the
 		 * user about possible write protection.
 		 */
@@ -220,12 +220,11 @@ int probe_spi_rems(struct flashctx *flash)
 	}
 
 	/* Test if this is a pure vendor match. */
-	if (id1 == flash->manufacture_id &&
-	    GENERIC_DEVICE_ID == flash->model_id)
+	if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id)
 		return 1;
 
 	/* Test if there is any vendor ID. */
-	if (GENERIC_MANUF_ID == flash->manufacture_id &&
+	if (GENERIC_MANUF_ID == chip->manufacture_id &&
 	    id1 != 0xff)
 		return 1;
 
@@ -267,7 +266,7 @@ int probe_spi_res1(struct flashctx *flash)
 
 	msg_cdbg("%s: id 0x%x\n", __func__, id2);
 
-	if (id2 != flash->model_id)
+	if (id2 != flash->chip->model_id)
 		return 0;
 
 	/* Print the status register to tell the
@@ -291,7 +290,7 @@ int probe_spi_res2(struct flashctx *flash)
 
 	msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
 
-	if (id1 != flash->manufacture_id || id2 != flash->model_id)
+	if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
 		return 0;
 
 	/* Print the status register to tell the
@@ -419,22 +418,23 @@ void spi_prettyprint_status_register_sst25vf040b(uint8_t status)
 
 int spi_prettyprint_status_register(struct flashctx *flash)
 {
+	const struct flashchip *chip = flash->chip;
 	uint8_t status;
 
 	status = spi_read_status_register(flash);
 	msg_cdbg("Chip status register is %02x\n", status);
-	switch (flash->manufacture_id) {
+	switch (chip->manufacture_id) {
 	case ST_ID:
-		if (((flash->model_id & 0xff00) == 0x2000) ||
-		    ((flash->model_id & 0xff00) == 0x2500))
+		if (((chip->model_id & 0xff00) == 0x2000) ||
+		    ((chip->model_id & 0xff00) == 0x2500))
 			spi_prettyprint_status_register_st_m25p(status);
 		break;
 	case MACRONIX_ID:
-		if ((flash->model_id & 0xff00) == 0x2000)
+		if ((chip->model_id & 0xff00) == 0x2000)
 			spi_prettyprint_status_register_st_m25p(status);
 		break;
 	case SST_ID:
-		switch (flash->model_id) {
+		switch (chip->model_id) {
 		case 0x2541:
 			spi_prettyprint_status_register_sst25vf016(status);
 			break;
@@ -704,7 +704,7 @@ int spi_block_erase_20(struct flashctx *flash, unsigned int addr,
 int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
-	if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
+	if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n",
 			__func__);
 		return -1;
@@ -715,7 +715,7 @@ int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
 int spi_block_erase_c7(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
-	if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
+	if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n",
 			__func__);
 		return -1;
@@ -820,7 +820,7 @@ static int spi_write_status_register_flag(struct flashctx *flash, int status, co
 
 int spi_write_status_register(struct flashctx *flash, int status)
 {
-	int feature_bits = flash->feature_bits;
+	int feature_bits = flash->chip->feature_bits;
 	int ret = 1;
 
 	if (!(feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) {
@@ -972,7 +972,7 @@ int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start,
 {
 	int rc = 0;
 	unsigned int i, j, starthere, lenhere, toread;
-	unsigned int page_size = flash->page_size;
+	unsigned int page_size = flash->chip->page_size;
 
 	/* Warning: This loop has a very unusual condition and body.
 	 * The loop needs to go through each page with at least one affected
@@ -1017,7 +1017,7 @@ int spi_write_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start,
 	 * spi_chip_write_256 have page_size set to max_writechunk_size, so
 	 * we're OK for now.
 	 */
-	unsigned int page_size = flash->page_size;
+	unsigned int page_size = flash->chip->page_size;
 
 	/* Warning: This loop has a very unusual condition and body.
 	 * The loop needs to go through each page with at least one affected
diff --git a/sst28sf040.c b/sst28sf040.c
index a9a740c..52e4256 100644
--- a/sst28sf040.c
+++ b/sst28sf040.c
@@ -119,7 +119,7 @@ static int erase_28sf040(struct flashctx *flash)
 int erase_chip_28sf040(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
-	if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
+	if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n",
 			__func__);
 		return -1;
diff --git a/sst49lfxxxc.c b/sst49lfxxxc.c
index 37f0628..bb21559 100644
--- a/sst49lfxxxc.c
+++ b/sst49lfxxxc.c
@@ -38,7 +38,7 @@ static int write_lockbits_block_49lfxxxc(struct flashctx *flash,
 static int write_lockbits_49lfxxxc(struct flashctx *flash, unsigned char bits)
 {
 	chipaddr registers = flash->virtual_registers;
-	unsigned int i, left = flash->total_size * 1024;
+	unsigned int i, left = flash->chip->total_size * 1024;
 	unsigned long address;
 
 	msg_cdbg("\nbios=0x%08lx\n", registers);
diff --git a/sst_fwhub.c b/sst_fwhub.c
index c802a33..a440a20 100644
--- a/sst_fwhub.c
+++ b/sst_fwhub.c
@@ -31,7 +31,7 @@ static int check_sst_fwhub_block_lock(struct flashctx *flash, int offset)
 
 	blockstatus = chip_readb(flash, registers + offset + 2);
 	msg_cdbg("Lock status for 0x%06x (size 0x%06x) is %02x, ",
-		     offset, flash->page_size, blockstatus);
+		     offset, flash->chip->page_size, blockstatus);
 	switch (blockstatus & 0x3) {
 	case 0x0:
 		msg_cdbg("full access\n");
@@ -72,7 +72,7 @@ int printlock_sst_fwhub(struct flashctx *flash)
 {
 	int i;
 
-	for (i = 0; i < flash->total_size * 1024; i += flash->page_size)
+	for (i = 0; i < flash->chip->total_size * 1024; i += flash->chip->page_size)
 		check_sst_fwhub_block_lock(flash, i);
 
 	return 0;
@@ -82,7 +82,7 @@ int unlock_sst_fwhub(struct flashctx *flash)
 {
 	int i, ret=0;
 
-	for (i = 0; i < flash->total_size * 1024; i += flash->page_size)
+	for (i = 0; i < flash->chip->total_size * 1024; i += flash->chip->page_size)
 	{
 		if (clear_sst_fwhub_block_lock(flash, i))
 		{
diff --git a/stm50flw0x0x.c b/stm50flw0x0x.c
index 9b6443e..e6c7c05 100644
--- a/stm50flw0x0x.c
+++ b/stm50flw0x0x.c
@@ -54,7 +54,7 @@ static int unlock_block_stm50flw0x0x(struct flashctx *flash, int offset)
 	/* Check, if it's is a top/bottom-block with 4k-sectors. */
 	/* TODO: What about the other types? */
 	if ((offset == 0) ||
-	    (offset == (flash->model_id == ST_M50FLW080A ? 0xE0000 : 0x10000))
+	    (offset == (flash->chip->model_id == ST_M50FLW080A ? 0xE0000 : 0x10000))
 	    || (offset == 0xF0000)) {
 
 		// unlock each 4k-sector
@@ -85,7 +85,7 @@ int unlock_stm50flw0x0x(struct flashctx *flash)
 {
 	int i;
 
-	for (i = 0; i < flash->total_size * 1024; i+= flash->page_size) {
+	for (i = 0; i < flash->chip->total_size * 1024; i+= flash->chip->page_size) {
 		if(unlock_block_stm50flw0x0x(flash, i)) {
 			msg_cerr("UNLOCK FAILED!\n");
 			return -1;
diff --git a/w29ee011.c b/w29ee011.c
index d2af23d..4df4687 100644
--- a/w29ee011.c
+++ b/w29ee011.c
@@ -29,11 +29,11 @@ int probe_w29ee011(struct flashctx *flash)
 	chipaddr bios = flash->virtual_memory;
 	uint8_t id1, id2;
 
-	if (!chip_to_probe || strcmp(chip_to_probe, flash->name)) {
+	if (!chip_to_probe || strcmp(chip_to_probe, flash->chip->name)) {
 		msg_cdbg("Old Winbond W29* probe method disabled because "
 			 "the probing sequence puts the AMIC A49LF040A in "
 			 "a funky state. Use 'flashrom -c %s' if you "
-			 "have a board with such a chip.\n", flash->name);
+			 "have a board with such a chip.\n", flash->chip->name);
 		return 0;
 	}
 
@@ -65,7 +65,7 @@ int probe_w29ee011(struct flashctx *flash)
 
 	msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
 
-	if (id1 == flash->manufacture_id && id2 == flash->model_id)
+	if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id)
 		return 1;
 
 	return 0;
diff --git a/w39.c b/w39.c
index 5f0c347..da61d23 100644
--- a/w39.c
+++ b/w39.c
@@ -138,11 +138,11 @@ static int printlock_w39_common(struct flashctx *flash, unsigned int offset)
 
 static int printlock_w39_fwh(struct flashctx *flash)
 {
-	unsigned int i, total_size = flash->total_size * 1024;
+	unsigned int i, total_size = flash->chip->total_size * 1024;
 	int ret = 0;
 	
 	/* Print lock status of the complete chip */
-	for (i = 0; i < total_size; i += flash->page_size)
+	for (i = 0; i < total_size; i += flash->chip->page_size)
 		ret |= printlock_w39_fwh_block(flash, i);
 
 	return ret;
@@ -150,10 +150,10 @@ static int printlock_w39_fwh(struct flashctx *flash)
 
 static int unlock_w39_fwh(struct flashctx *flash)
 {
-	unsigned int i, total_size = flash->total_size * 1024;
+	unsigned int i, total_size = flash->chip->total_size * 1024;
 	
 	/* Unlock the complete chip */
-	for (i = 0; i < total_size; i += flash->page_size)
+	for (i = 0; i < total_size; i += flash->chip->page_size)
 		if (unlock_w39_fwh_block(flash, i))
 			return -1;
 
-- 
Kind regards, Stefan Tauner

