changeset 405:a212b4968b29

fc-loadtool flash: another refactoring: geometry vs. command set
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Tue, 17 Jun 2014 00:33:05 +0000
parents 7daea2476062
children 0b8e5072abde
files loadtools/Makefile loadtools/flash.h loadtools/flashops.c loadtools/flerase.c loadtools/flmain.c loadtools/flmisc.c loadtools/flprogbin.c loadtools/flprogsrec.c loadtools/flutil.c loadtools/ltflash.c
diffstat 10 files changed, 658 insertions(+), 600 deletions(-) [+]
line wrap: on
line diff
--- a/loadtools/Makefile	Mon Jun 16 01:15:17 2014 +0000
+++ b/loadtools/Makefile	Tue Jun 17 00:33:05 2014 +0000
@@ -8,11 +8,11 @@
 IRAM_OBJS=	defpath.o hexdecode.o hwparam.o hwparamstubs.o romload.o \
 		sercomm.o sertool.o srecreader.o ttypassthru.o ${EXTRA_OBJ}
 
-LOADTOOL_OBJS=	crc32tab.o defpath.o flerase.o flprogbin.o flprogsrec.o \
-		flutil.o hexdecode.o hwparam.o labaud.o ltdispatch.o ltdump.o \
-		ltexit.o ltflash.o lthelp.o ltmain.o ltmisc.o ltpassthru.o \
-		ltscript.o romload.o sercomm.o srecreader.o tpinterf.o \
-		tpinterf2.o tpinterf3.o ${EXTRA_OBJ}
+LOADTOOL_OBJS=	crc32tab.o defpath.o flashops.o flmain.o flmisc.o flprogbin.o \
+		flprogsrec.o flutil.o hexdecode.o hwparam.o labaud.o \
+		ltdispatch.o ltdump.o ltexit.o lthelp.o ltmain.o ltmisc.o \
+		ltpassthru.o ltscript.o romload.o sercomm.o srecreader.o \
+		tpinterf.o tpinterf2.o tpinterf3.o ${EXTRA_OBJ}
 
 XRAM_OBJS=	chainload.o clmain.o defpath.o hexdecode.o hwparam.o \
 		hwparamstubs.o initscript.o labaud.o romload.o sercomm.o \
--- a/loadtools/flash.h	Mon Jun 16 01:15:17 2014 +0000
+++ b/loadtools/flash.h	Tue Jun 17 00:33:05 2014 +0000
@@ -14,9 +14,11 @@
 
 #define	CFI_MAX_REGIONS		4
 
-/* The info in struct cfi_info can be either gathered from CFI or hard-coded. */
-struct cfi_info {
-	uint16_t			cmdset_style;
+/*
+ * The info in struct flash_geom can be either
+ * gathered from CFI or hard-coded.
+ */
+struct flash_geom {
 	uint32_t			total_size;
 	unsigned			nregions;
 	struct flash_region_desc	regions[CFI_MAX_REGIONS];
@@ -30,7 +32,7 @@
 
 struct flash_bank_desc {
 	uint32_t		align_size;
-	struct cfi_info		*hard_cfi;
+	struct flash_geom	*geom;
 	struct flash_idcheck	*idcheck_table;
 	unsigned		idcheck_num;
 };
@@ -39,6 +41,7 @@
 	char			*name;
 	struct flash_bank_desc	*bank_desc;
 	unsigned		nbanks;
+	struct flash_cmdset	*cmdset;
 };
 
 /* the following structures describe flash banks as accessible to us */
@@ -48,10 +51,22 @@
 	uint32_t	size;
 };
 
+struct flash_cmdset {
+	char	*cmdset_name;
+	int	(*reset_cmd)();
+	int	(*status_cmd)();
+	int	(*unlock_sector)();
+	int	(*erase_sector)();
+	int	(*prep_for_program)();
+	char	*loadagent_setbase_cmd;
+	char	*loadagent_program_cmd;
+};
+
 struct flash_bank_info {
 	uint32_t		base_addr;
 	struct flash_bank_desc	*bank_desc;
-	struct cfi_info		*cfi;
+	struct flash_geom	*geom;
+	struct flash_cmdset	*ops;
 	struct sector_info	*sectors;
 	int			idcheck_done;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/flashops.c	Tue Jun 17 00:33:05 2014 +0000
@@ -0,0 +1,95 @@
+/*
+ * This module implements those flash operations which are dependent
+ * on the AMD vs. Intel command set style.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+#include "flash.h"
+
+/* common stub functions */
+
+static
+noop()
+{
+	return(0);
+}
+
+static
+invalid()
+{
+	fprintf(stderr,
+	      "This operation is not applicable to the selected flash type\n");
+	return(-1);
+}
+
+/* AMD flash functions */
+
+amd_reset_cmd(bi)
+	struct flash_bank_info *bi;
+{
+	if (do_w16(bi->base_addr + 0xAAA, 0xF0)) {
+		fprintf(stderr,
+	"unexpected response to w16 when resetting flash to read mode!\n");
+		return(-1);
+	}
+	return(0);
+}
+
+amd_sector_erase(bi, sp)
+	struct flash_bank_info *bi;
+	struct sector_info *sp;
+{
+	int stat;
+	uint16_t flstat;
+	time_t start_time, curtime;
+
+	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA);
+	if (stat) {
+bad_w16:	fprintf(stderr,
+	"unexpected response to w16 in erase cmd sequence - aborting\n");
+		return(-1);
+	}
+	stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55);
+	if (stat)
+		goto bad_w16;
+	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x80);
+	if (stat)
+		goto bad_w16;
+	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA);
+	if (stat)
+		goto bad_w16;
+	stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55);
+	if (stat)
+		goto bad_w16;
+	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x30);
+	if (stat)
+		goto bad_w16;
+	start_time = time(0);
+	for (;;) {
+		stat = do_r16(bi->base_addr + sp->start, &flstat);
+		if (stat)
+			return(stat);	/* error msg already printed */
+		if (flstat == 0xFFFF)
+			return(0);
+		curtime = time(0);
+		if (curtime >= start_time + 20) {
+			fprintf(stderr, "erase timeout, aborting\n");
+			return(-1);
+		}
+	}
+}
+
+struct flash_cmdset flash_cmdset_amd = {
+	.cmdset_name		= "AMD",
+	.reset_cmd		= amd_reset_cmd,
+	.status_cmd		= invalid,
+	.unlock_sector		= invalid,
+	.erase_sector		= amd_sector_erase,
+	.prep_for_program	= noop,
+	.loadagent_setbase_cmd	= "AMFB",
+	.loadagent_program_cmd	= "AMFW",
+};
--- a/loadtools/flerase.c	Mon Jun 16 01:15:17 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * This module implements the flash erase operation
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <time.h>
-#include "flash.h"
-
-extern struct flash_bank_info flash_bank_info[2];
-
-do_sector_erase(bi, sp)
-	struct flash_bank_info *bi;
-	struct sector_info *sp;
-{
-	int stat;
-	uint16_t flstat;
-	time_t start_time, curtime;
-
-	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA);
-	if (stat) {
-bad_w16:	fprintf(stderr,
-	"unexpected response to w16 in erase cmd sequence - aborting\n");
-		return(-1);
-	}
-	stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55);
-	if (stat)
-		goto bad_w16;
-	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x80);
-	if (stat)
-		goto bad_w16;
-	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA);
-	if (stat)
-		goto bad_w16;
-	stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55);
-	if (stat)
-		goto bad_w16;
-	stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x30);
-	if (stat)
-		goto bad_w16;
-	start_time = time(0);
-	for (;;) {
-		stat = do_r16(bi->base_addr + sp->start, &flstat);
-		if (stat)
-			return(stat);	/* error msg already printed */
-		if (flstat == 0xFFFF)
-			return(0);
-		curtime = time(0);
-		if (curtime >= start_time + 20) {
-			fprintf(stderr, "erase timeout, aborting\n");
-			return(-1);
-		}
-	}
-}
-
-flashcmd_erase(argc, argv, bank)
-	char **argv;
-{
-	struct flash_bank_info *bi;
-	u_long offset, len;
-	char *strtoul_endp;
-	struct sector_info *startsec, *endsec, *sp;
-	int stat;
-
-	if (argc != 4) {
-inv:		fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n",
-			argv[0], argv[1]);
-		return(-1);
-	}
-	offset = strtoul(argv[2], &strtoul_endp, 16);
-	if (*strtoul_endp)
-		goto inv;
-	if (flash_get_cfi(bank) < 0)
-		return(-1);
-	bi = flash_bank_info + bank;
-	if (bi->cfi->cmdset_style != 2) {
-		fprintf(stderr,
-"error: this command is currently only implemented for AMD-style flash\n");
-		return(-1);
-	}
-	if (offset >= bi->cfi->total_size) {
-		fprintf(stderr,
-		"error: specified offset exceeds flash bank size (0x%lx)\n",
-			(u_long) bi->cfi->total_size);
-		return(-1);
-	}
-	len = strtoul(argv[3], &strtoul_endp, 16);
-	if (*strtoul_endp)
-		goto inv;
-	if (len > bi->cfi->total_size - offset) {
-		fprintf(stderr,
-	"error: specified offset+length exceed flash bank size (0x%lx)\n",
-			(u_long) bi->cfi->total_size);
-		return(-1);
-	}
-	if (!len) {
-		printf("Zero length specified - nothing to do!\n");
-		return(0);
-	}
-	/* now enforce sector alignment for both offset and length */
-	if (get_flash_sector_table(bank) < 0)
-		return(-1);
-	if (get_flash_sector_range(bi, offset, len, &startsec, &endsec) < 0)
-		return(-1);
-	stat = flash_id_check(bank, 0);
-	if (stat)
-		return(stat);
-	printf("Erasing %d sector(s)\n", endsec - startsec);
-	for (sp = startsec; sp < endsec; sp++) {
-		stat = do_sector_erase(bi, sp);
-		if (stat)
-			return(stat);
-		putchar('.');
-		fflush(stdout);
-	}
-	putchar('\n');
-	return(0);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/flmain.c	Tue Jun 17 00:33:05 2014 +0000
@@ -0,0 +1,251 @@
+/*
+ * This module is the main entry point for fc-loadtool flash functions
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include "flash.h"
+
+/* K5A32xx device description */
+
+static struct flash_geom k5a32xx_topboot_geom = {
+	.total_size	= 0x400000,
+	.nregions	= 2,
+	.regions	= {0x10000, 63, 0x2000, 8},
+	.total_sectors	= 71,
+};
+
+static struct flash_idcheck k5a32xx_topboot_idcheck[2] = {
+	{0x00, 0x00EC},
+	{0x02, 0x22A0}
+};
+
+static struct flash_bank_desc k5a32xx_topboot_bankdesc = {
+	0x400000, &k5a32xx_topboot_geom, k5a32xx_topboot_idcheck, 2
+};
+
+/* S{29,71}PL129N device description */
+
+static struct flash_geom pl129n_ce1_geom = {
+	.total_size	= 0x800000,
+	.nregions	= 2,
+	.regions	= {0x10000, 4, 0x40000, 31},
+	.total_sectors	= 35,
+};
+
+static struct flash_geom pl129n_ce2_geom = {
+	.total_size	= 0x800000,
+	.nregions	= 2,
+	.regions	= {0x40000, 31, 0x10000, 4},
+	.total_sectors	= 35,
+};
+
+static struct flash_idcheck pl129n_idcheck[4] = {
+	{0x00, 0x0001},
+	{0x02, 0x227E},
+	{0x1C, 0x2221},
+	{0x1E, 0x2200}
+};
+
+static struct flash_bank_desc pl129n_banks[2] = {
+	{0x800000, &pl129n_ce1_geom, pl129n_idcheck, 4},
+	{0x800000, &pl129n_ce2_geom, pl129n_idcheck, 4}
+};
+
+/* bank configurations for CFI */
+
+static struct flash_bank_desc cfi_4M_bankdesc = {
+	0x400000, 0, 0, 0
+};
+
+static struct flash_bank_desc cfi_8M_bankdesc = {
+	0x800000, 0, 0, 0
+};
+
+/* list of supported flash devices */
+
+extern struct flash_cmdset flash_cmdset_amd;
+
+struct flash_device_desc flash_device_list[] = {
+	{"cfi-4M", &cfi_4M_bankdesc, 1, 0},
+	{"cfi-8M", &cfi_8M_bankdesc, 1, 0},
+	{"k5a32xx_t", &k5a32xx_topboot_bankdesc, 1, &flash_cmdset_amd},
+	{"pl129n", pl129n_banks, 2, &flash_cmdset_amd},
+	{0, 0, 0, 0}	/* array terminator */
+};
+
+/* the following variables describe our selected flash device */
+
+struct flash_device_desc *selected_flash_device;
+struct flash_bank_info flash_bank_info[2];
+
+/* called from hwparam.c config file parser */
+void
+set_flash_device(arg, filename_for_errs, lineno_for_errs)
+	char *arg;
+	char *filename_for_errs;
+	int lineno_for_errs;
+{
+	char *cp, *np, *ep;
+	struct flash_device_desc *tp;
+	int bank;
+	struct flash_bank_info *bi;
+
+	if (selected_flash_device) {
+		fprintf(stderr, "%s line %d: duplicate flash setting\n",
+			filename_for_errs, lineno_for_errs);
+		exit(1);
+	}
+	for (cp = arg; isspace(*cp); cp++)
+		;
+	if (!*cp || *cp == '#') {
+too_few_arg:	fprintf(stderr,
+			"%s line %d: flash setting: too few arguments\n",
+			filename_for_errs, lineno_for_errs);
+		exit(1);
+	}
+	for (np = cp; *cp && !isspace(*cp); cp++)
+		;
+	if (*cp)
+		*cp++ = '\0';
+	for (tp = flash_device_list; tp->name; tp++)
+		if (!strcmp(tp->name, np))
+			break;
+	if (!tp->name) {
+		fprintf(stderr,
+			"%s line %d: unknown flash device \"%s\"\n",
+			filename_for_errs, lineno_for_errs, np);
+		exit(1);
+	}
+	selected_flash_device = tp;
+
+	/* now initialize flash_bank_info */
+	for (bank = 0; bank < selected_flash_device->nbanks; bank++) {
+		while (isspace(*cp))
+			cp++;
+		if (!*cp || *cp == '#')
+			goto too_few_arg;
+		for (np = cp; *cp && !isspace(*cp); cp++)
+			;
+		if (*cp)
+			*cp++ = '\0';
+		bi = flash_bank_info + bank;
+		bi->base_addr = strtoul(np, &ep, 16);
+		if (*ep) {
+			fprintf(stderr,
+"%s line %d: syntax error (base addr expected after flash device type)\n",
+				filename_for_errs, lineno_for_errs);
+			exit(1);
+		}
+		/* the rest comes from the flash device type */
+		bi->bank_desc = selected_flash_device->bank_desc + bank;
+		if (bi->base_addr & (bi->bank_desc->align_size - 1)) {
+			fprintf(stderr,
+"%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n",
+				filename_for_errs, lineno_for_errs, bank,
+				(u_long) bi->bank_desc->align_size);
+			exit(1);
+		}
+		bi->geom = bi->bank_desc->geom;
+		bi->ops = selected_flash_device->cmdset;
+	}
+	while (isspace(*cp))
+		cp++;
+	if (*cp && *cp != '#') {
+		fprintf(stderr,
+			"%s line %d: flash setting: too many arguments\n",
+			filename_for_errs, lineno_for_errs);
+		exit(1);
+	}
+}
+
+flashcmd_help()
+{
+	return loadtool_help("flash");
+}
+
+flashcmd_info(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+
+	if (argc > 2) {
+		fprintf(stderr, "error: too many arguments\n");
+		return(-1);
+	}
+	bi = flash_bank_info + bank;
+	printf("Flash device type: %s\n", selected_flash_device->name);
+	printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr);
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	printf("Bank %d total size: %lx\n", bank,
+		(u_long) bi->geom->total_size);
+	printf("Sectors in bank %d: %u (%u regions)\n", bank,
+		bi->geom->total_sectors, bi->geom->nregions);
+	printf("Command set style: %s\n", bi->ops->cmdset_name);
+	flash_id_check(bank, 1);
+	if (selected_flash_device->nbanks == 2 && !bank)
+	    printf("\nFlash device has 2 banks; flash2 command available\n");
+	return(0);
+}
+
+extern int flashcmd_blankchk();
+extern int flashcmd_dump2file();
+extern int flashcmd_erase();
+extern int flashcmd_progbin();
+extern int flashcmd_program_m0();
+extern int flashcmd_program_srec();
+extern int flashcmd_quickprog();
+extern int flashcmd_sectors();
+
+static struct cmdtab {
+	char *cmd;
+	int (*func)();
+} cmdtab[] = {
+	{"blankchk", flashcmd_blankchk},
+	{"dump2bin", flashcmd_dump2file},
+	{"dump2srec", flashcmd_dump2file},
+	{"erase", flashcmd_erase},
+	{"help", flashcmd_help},
+	{"info", flashcmd_info},
+	{"program-bin", flashcmd_progbin},
+	{"program-m0", flashcmd_program_m0},
+	{"program-srec", flashcmd_program_srec},
+	{"quickprog", flashcmd_quickprog},
+	{"sectors", flashcmd_sectors},
+	{0, 0}
+};
+
+cmd_flash(argc, argv)
+	char **argv;
+{
+	int bank;
+	struct cmdtab *tp;
+
+	if (!selected_flash_device) {
+		fprintf(stderr, "No flash configuration defined\n");
+		return(-1);
+	}
+	if (argv[0][5] == '2') {
+		if (selected_flash_device->nbanks < 2) {
+			fprintf(stderr, "Flash device %s has only one bank\n",
+				selected_flash_device->name);
+			return(-1);
+		}
+		bank = 1;
+	} else
+		bank = 0;
+	for (tp = cmdtab; tp->cmd; tp++)
+		if (!strcmp(tp->cmd, argv[1]))
+			break;
+	if (!tp->func) {
+		fprintf(stderr, "%s %s: unknown/unimplemented subcommand\n",
+			argv[0], argv[1]);
+		return(-1);
+	}
+	return tp->func(argc, argv, bank);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/flmisc.c	Tue Jun 17 00:33:05 2014 +0000
@@ -0,0 +1,214 @@
+/*
+ * Miscellaneous flash commands (fc-loadtool) are implemented here
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include "flash.h"
+
+extern struct flash_bank_info flash_bank_info[2];
+
+flashcmd_blankchk(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+	u_long offset, len;
+	char *strtoul_endp;
+	char *targv[4], targ_start[10], targ_len[10];
+
+	if (argc != 4) {
+inv:		fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n",
+			argv[0], argv[1]);
+		return(-1);
+	}
+	offset = strtoul(argv[2], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	bi = flash_bank_info + bank;
+	if (offset >= bi->geom->total_size) {
+		fprintf(stderr,
+		"error: specified offset exceeds flash bank size (0x%lx)\n",
+			(u_long) bi->geom->total_size);
+		return(-1);
+	}
+	len = strtoul(argv[3], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	if (len > bi->geom->total_size - offset) {
+		fprintf(stderr,
+	"error: specified offset+length exceed flash bank size (0x%lx)\n",
+			(u_long) bi->geom->total_size);
+		return(-1);
+	}
+	sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset);
+	sprintf(targ_len, "%lx", len);
+	targv[0] = "blankchk";
+	targv[1] = targ_start;
+	targv[2] = targ_len;
+	targv[3] = 0;
+	tpinterf_make_cmd(targv);
+	if (tpinterf_send_cmd() < 0)
+		return(-1);
+	return tpinterf_pass_output(10);	/* 10 s timeout */
+}
+
+flashcmd_dump2file(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+	u_long offset, dumplen, maxlen;
+	char *strtoul_endp;
+	int format;
+
+	if (argc < 3 || argc > 5) {
+inv:		fprintf(stderr, "usage: %s %s outfile [offset [length]]\n",
+			argv[0], argv[1]);
+		return(-1);
+	}
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	bi = flash_bank_info + bank;
+	if (argc >= 4) {
+		offset = strtoul(argv[3], &strtoul_endp, 16);
+		if (*strtoul_endp)
+			goto inv;
+		if (offset >= bi->geom->total_size) {
+			fprintf(stderr,
+		"error: specified offset exceeds flash bank size (0x%lx)\n",
+				(u_long) bi->geom->total_size);
+			return(-1);
+		}
+	} else
+		offset = 0;
+	maxlen = bi->geom->total_size - offset;
+	if (argc >= 5) {
+		dumplen = strtoul(argv[4], &strtoul_endp, 16);
+		if (*strtoul_endp)
+			goto inv;
+		if (dumplen > maxlen) {
+			fprintf(stderr,
+	"error: specified offset+length exceed flash bank size (0x%lx)\n",
+				(u_long) bi->geom->total_size);
+			return(-1);
+		}
+	} else
+		dumplen = maxlen;
+	switch (argv[1][5]) {
+	case 'b':
+		format = 0;
+		break;
+	case 's':
+		format = 1;
+		break;
+	default:
+		fprintf(stderr,
+			"internal bug: bad format in flashcmd_dump2file()\n");
+		return(-1);
+	}
+	return loadtool_memdump(bi->base_addr + offset, dumplen, argv[2],
+				format);
+}
+
+flashcmd_erase(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+	u_long offset, len;
+	char *strtoul_endp;
+	struct sector_info *startsec, *endsec, *sp;
+	int stat;
+
+	if (argc != 4) {
+inv:		fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n",
+			argv[0], argv[1]);
+		return(-1);
+	}
+	offset = strtoul(argv[2], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	bi = flash_bank_info + bank;
+	if (offset >= bi->geom->total_size) {
+		fprintf(stderr,
+		"error: specified offset exceeds flash bank size (0x%lx)\n",
+			(u_long) bi->geom->total_size);
+		return(-1);
+	}
+	len = strtoul(argv[3], &strtoul_endp, 16);
+	if (*strtoul_endp)
+		goto inv;
+	if (len > bi->geom->total_size - offset) {
+		fprintf(stderr,
+	"error: specified offset+length exceed flash bank size (0x%lx)\n",
+			(u_long) bi->geom->total_size);
+		return(-1);
+	}
+	if (!len) {
+		printf("Zero length specified - nothing to do!\n");
+		return(0);
+	}
+	/* now enforce sector alignment for both offset and length */
+	if (get_flash_sector_table(bank) < 0)
+		return(-1);
+	if (get_flash_sector_range(bi, offset, len, &startsec, &endsec) < 0)
+		return(-1);
+	stat = flash_id_check(bank, 0);
+	if (stat)
+		return(stat);
+	printf("Erasing %d sector(s)\n", endsec - startsec);
+	for (sp = startsec; sp < endsec; sp++) {
+		stat = bi->ops->erase_sector(bi, sp);
+		if (stat)
+			return(stat);
+		putchar('.');
+		fflush(stdout);
+	}
+	putchar('\n');
+	return(0);
+}
+
+flashcmd_quickprog(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+	char *targv[4], targ_base[10];
+	int stat;
+
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	if (argc != 4) {
+		fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n",
+			argv[0], argv[1]);
+		return(-1);
+	}
+	bi = flash_bank_info + bank;
+	sprintf(targ_base, "%lx", (u_long) bi->base_addr);
+	targv[0] = bi->ops->loadagent_setbase_cmd;
+	targv[1] = targ_base;
+	targv[2] = 0;
+	tpinterf_make_cmd(targv);
+	if (tpinterf_send_cmd() < 0)
+		return(-1);
+	stat = tpinterf_pass_output(1);
+	if (stat)
+		return(stat);
+	targv[0] = bi->ops->loadagent_program_cmd;
+	targv[1] = argv[2];
+	targv[2] = argv[3];
+	targv[3] = 0;
+	if (tpinterf_make_cmd(targv) < 0) {
+		fprintf(stderr,
+			"error: unable to form AMFW/INFW target command\n");
+		return(-1);
+	}
+	if (tpinterf_send_cmd() < 0)
+		return(-1);
+	return tpinterf_pass_output(1);
+}
--- a/loadtools/flprogbin.c	Mon Jun 16 01:15:17 2014 +0000
+++ b/loadtools/flprogbin.c	Tue Jun 17 00:33:05 2014 +0000
@@ -1,5 +1,5 @@
 /*
- * In this module we are going to implement the flash program-bin command:
+ * This module implements the flash program-bin command:
  * programming flash using a binary file as the data source.
  */
 
@@ -38,15 +38,10 @@
 	if (flash_get_cfi(bank) < 0)
 		return(-1);
 	bi = flash_bank_info + bank;
-	if (bi->cfi->cmdset_style != 2) {
-		fprintf(stderr,
-"error: this command is currently only implemented for AMD-style flash\n");
-		return(-1);
-	}
-	if (flashoff >= bi->cfi->total_size) {
+	if (flashoff >= bi->geom->total_size) {
 		fprintf(stderr,
 		"error: specified flash offset exceeds bank size (0x%lx)\n",
-			(u_long) bi->cfi->total_size);
+			(u_long) bi->geom->total_size);
 		return(-1);
 	}
 	if (flashoff & 1) {
@@ -97,10 +92,10 @@
 		fclose(binf);
 		return(0);
 	}
-	if (len > bi->cfi->total_size - flashoff) {
+	if (len > bi->geom->total_size - flashoff) {
 		fprintf(stderr,
 	"error: specified flash offset+length exceed bank size (0x%lx)\n",
-			(u_long) bi->cfi->total_size);
+			(u_long) bi->geom->total_size);
 		fclose(binf);
 		return(-1);
 	}
@@ -116,7 +111,7 @@
 		return(-1);
 	}
 	sprintf(shortarg, "%lx", (u_long) bi->base_addr);
-	targv[0] = "AMFB";
+	targv[0] = bi->ops->loadagent_setbase_cmd;
 	targv[1] = shortarg;
 	targv[2] = 0;
 	printf("Setting flash base address: %s %s\n", targv[0], targv[1]);
@@ -131,7 +126,7 @@
 		return(cc);
 	}
 	fseek(binf, fileoff, SEEK_SET);
-	targv[0] = "AMFW";
+	targv[0] = bi->ops->loadagent_program_cmd;
 	targv[1] = shortarg;
 	targv[2] = longarg;
 	targv[3] = 0;
--- a/loadtools/flprogsrec.c	Mon Jun 16 01:15:17 2014 +0000
+++ b/loadtools/flprogsrec.c	Tue Jun 17 00:33:05 2014 +0000
@@ -1,7 +1,6 @@
 /*
- * In this module we are going to implement the flash program-srec and
- * flash program-m0 commands: programming flash using S-record files
- * as the data source.
+ * This module implements the flash program-srec and flash program-m0 commands:
+ * programming flash using S-record files as the data source.
  */
 
 #include <sys/types.h>
@@ -25,11 +24,6 @@
 	if (flash_get_cfi(bank) < 0)
 		return(-1);
 	bi = flash_bank_info + bank;
-	if (bi->cfi->cmdset_style != 2) {
-		fprintf(stderr,
-"error: this command is currently only implemented for AMD-style flash\n");
-		return(-1);
-	}
 	srr.filename = imgfile;
 	resp = open_srec_file(&srr);
 	if (resp < 0)
@@ -40,7 +34,7 @@
 		return(resp);
 	}
 	sprintf(shortarg, "%lx", (u_long) bi->base_addr);
-	targv[0] = "AMFB";
+	targv[0] = bi->ops->loadagent_setbase_cmd;
 	targv[1] = shortarg;
 	targv[2] = 0;
 	printf("Setting flash base address: %s %s\n", targv[0], targv[1]);
@@ -54,7 +48,7 @@
 		fclose(srr.openfile);
 		return(resp);
 	}
-	targv[0] = "AMFW";
+	targv[0] = bi->ops->loadagent_program_cmd;
 	targv[1] = shortarg;
 	targv[2] = longarg;
 	targv[3] = 0;
@@ -98,8 +92,8 @@
 			fclose(srr.openfile);
 			return(-1);
 		}
-		srr.addr &= bi->cfi->total_size - 1;
-		if (srr.addr + srr.datalen > bi->cfi->total_size) {
+		srr.addr &= bi->geom->total_size - 1;
+		if (srr.addr + srr.datalen > bi->geom->total_size) {
 			fprintf(stderr,
 			"%s line %d: goes past the end of the flash bank\n",
 				srr.filename, srr.lineno);
--- a/loadtools/flutil.c	Mon Jun 16 01:15:17 2014 +0000
+++ b/loadtools/flutil.c	Tue Jun 17 00:33:05 2014 +0000
@@ -9,6 +9,8 @@
 #include "flash.h"
 
 extern struct flash_bank_info flash_bank_info[2];
+extern struct flash_cmdset flash_cmdset_amd;
+extern struct flash_cmdset flash_cmdset_intel;
 
 static int
 cfi_read_byte(bi, off, ret16p)
@@ -37,29 +39,17 @@
 	return(0);
 }
 
-static int
-cfi_id_return_to_read_mode(bi)
-	struct flash_bank_info *bi;
-{
-	if (do_w16(bi->base_addr + 0xAAA, 0xF0)) {
-		fprintf(stderr,
-	"unexpected response to w16 when resetting flash to read mode!\n");
-		return(-1);
-	}
-	return(0);
-}
-
 flash_get_cfi(bank)
 {
 	struct flash_bank_info *bi;
-	struct cfi_info *cfi;
+	struct flash_geom *geom;
 	struct flash_region_desc *reg;
 	int nr;
-	uint16_t rdval;
+	uint16_t rdval, cmdset_id;
 	uint32_t size_check;
 
 	bi = flash_bank_info + bank;
-	if (bi->cfi)
+	if (bi->geom)
 		return(0);
 	printf("Performing CFI query\n");
 	if (do_w16(bi->base_addr + 0xAA, 0x98)) {
@@ -71,7 +61,7 @@
 		return(-1);
 	if (rdval != 'Q') {
 noqry:		fprintf(stderr, "error: no QRY response from flash\n");
-		cfi_id_return_to_read_mode(bi);
+		amd_reset_cmd(bi);
 		return(-1);
 	}
 	if (cfi_read_byte(bi, 0x11, &rdval) < 0)
@@ -82,35 +72,52 @@
 		return(-1);
 	if (rdval != 'Y')
 		goto noqry;
-	cfi = malloc(sizeof(struct cfi_info));
-	if (!cfi) {
+	if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0)
+		return(-1);
+	if (!bi->ops) {
+		switch (cmdset_id) {
+		case 2:
+			bi->ops = &flash_cmdset_amd;
+			break;
+#if 0
+		case 3:
+			bi->ops = &flash_cmdset_intel;
+			break;
+#endif
+		default:
+			fprintf(stderr, "error: command set %04X unsupported\n",
+				cmdset_id);
+			amd_reset_cmd(bi);
+			return(-1);
+		}
+	}
+	geom = malloc(sizeof(struct flash_geom));
+	if (!geom) {
 		fprintf(stderr,
-		"unable to malloc buffer for flash bank %d CFI structure\n",
+	"unable to malloc buffer for flash bank %d CFI geometry structure\n",
 			bank);
-		cfi_id_return_to_read_mode(bi);
-		return(-1);
-	}
-	if (cfi_read_twobyte(bi, 0x13, &cfi->cmdset_style) < 0) {
-free_and_immed_out:
-		free(cfi);
+		bi->ops->reset_cmd(bi);
 		return(-1);
 	}
 	/* total device size */
-	if (cfi_read_byte(bi, 0x27, &rdval) < 0)
-		goto free_and_immed_out;
+	if (cfi_read_byte(bi, 0x27, &rdval) < 0) {
+free_and_immed_out:
+		free(geom);
+		return(-1);
+	}
 	if (rdval < 20 || rdval > 24) {
 		fprintf(stderr,
 			"error: CFI reports unreasonable device size\n");
 free_and_clean_out:
-		free(cfi);
-		cfi_id_return_to_read_mode(bi);
+		free(geom);
+		bi->ops->reset_cmd(bi);
 		return(-1);
 	}
-	cfi->total_size = 1 << rdval;
-	if (cfi->total_size > bi->bank_desc->align_size) {
+	geom->total_size = 1 << rdval;
+	if (geom->total_size > bi->bank_desc->align_size) {
 		fprintf(stderr,
 	"error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n",
-			(u_long) cfi->total_size, bi->bank_desc->align_size);
+			(u_long) geom->total_size, bi->bank_desc->align_size);
 		goto free_and_clean_out;
 	}
 	if (cfi_read_byte(bi, 0x2C, &rdval) < 0)
@@ -120,11 +127,11 @@
 			"error: CFI reports unreasonable # of erase regions\n");
 		goto free_and_clean_out;
 	}
-	cfi->nregions = rdval;
-	cfi->total_sectors = 0;
+	geom->nregions = rdval;
+	geom->total_sectors = 0;
 	size_check = 0;
-	for (nr = 0; nr < cfi->nregions; nr++) {
-		reg = cfi->regions + nr;
+	for (nr = 0; nr < geom->nregions; nr++) {
+		reg = geom->regions + nr;
 		if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0)
 			goto free_and_immed_out;
 		if (rdval > 255) {
@@ -134,7 +141,7 @@
 			goto free_and_clean_out;
 		}
 		reg->nsectors = rdval + 1;
-		cfi->total_sectors += reg->nsectors;
+		geom->total_sectors += reg->nsectors;
 		if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0)
 			goto free_and_immed_out;
 		if (rdval < 0x20 || rdval > 0x400) {
@@ -146,31 +153,30 @@
 		reg->sector_size = rdval << 8;
 		size_check += reg->sector_size * reg->nsectors;
 	}
-	if (cfi_id_return_to_read_mode(bi) < 0) {
+	if (bi->ops->reset_cmd(bi) < 0) {
 		/* error msg already printed */
-		free(cfi);
+		free(geom);
 		return(-1);
 	}
-	if (size_check != cfi->total_size) {
+	if (size_check != geom->total_size) {
 		fprintf(stderr,
 "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n",
-			(u_long) size_check, (u_long) cfi->total_size);
-		free(cfi);
+			(u_long) size_check, (u_long) geom->total_size);
+		free(geom);
 		return(-1);
 	}
 	/* all checks passed */
-	bi->cfi = cfi;
+	bi->geom = geom;
 	printf(
-"CFI query successful: total size %lx, %u sectors, command set style %04X\n\n",
-		(u_long) cfi->total_size, cfi->total_sectors,
-		cfi->cmdset_style);
+"CFI query successful: total size %lx, %u sectors, command set style %04X\n",
+		(u_long) geom->total_size, geom->total_sectors, cmdset_id);
 	return(1);
 }
 
 get_flash_sector_table(bank)
 {
 	struct flash_bank_info *bi;
-	struct cfi_info *cfi;
+	struct flash_geom *geom;
 	struct flash_region_desc *reg;
 	struct sector_info *sp;
 	uint32_t offset;
@@ -182,9 +188,9 @@
 	i = flash_get_cfi(bank);
 	if (i < 0)
 		return(i);
-	cfi = bi->cfi;
+	geom = bi->geom;
 	sp = (struct sector_info *) malloc(sizeof(struct sector_info)
-						* (cfi->total_sectors + 1));
+						* (geom->total_sectors + 1));
 	if (!sp) {
 		fprintf(stderr,
 		"unable to malloc buffer for flash bank %d sector table\n",
@@ -194,8 +200,8 @@
 	bi->sectors = sp;
 	/* now fill it */
 	offset = 0;
-	for (nr = 0; nr < cfi->nregions; nr++) {
-		reg = cfi->regions + nr;
+	for (nr = 0; nr < geom->nregions; nr++) {
+		reg = geom->regions + nr;
 		for (i = 0; i < reg->nsectors; i++) {
 			sp->start = offset;
 			sp->size = reg->sector_size;
@@ -204,12 +210,12 @@
 		}
 	}
 	/* sanity checks */
-	if (sp - bi->sectors != cfi->total_sectors) {
+	if (sp - bi->sectors != geom->total_sectors) {
 		fprintf(stderr,
 	"BUG in get_flash_sector_table(): wrong # of sectors at the end\n");
 		abort();
 	}
-	if (offset != cfi->total_size) {
+	if (offset != geom->total_size) {
 		fprintf(stderr,
 		"BUG in get_flash_sector_table(): wrong offset at the end\n");
 		abort();
@@ -233,7 +239,7 @@
 	if (get_flash_sector_table(bank) < 0)
 		return(-1);
 	bi = flash_bank_info + bank;
-	printf("%u sectors in flash bank %d:\n", bi->cfi->total_sectors, bank);
+	printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank);
 	printf("Offset    Size\n");
 	for (sp = bi->sectors; sp->size; sp++)
 		printf("%08lX  %lx\n", (u_long) sp->start, (u_long) sp->size);
--- a/loadtools/ltflash.c	Mon Jun 16 01:15:17 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,392 +0,0 @@
-/*
- * This module contains the "core" of fc-loadtool flash operations;
- * fl*.c modules contain the rest.
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include "flash.h"
-
-/* K5A32xx device description */
-
-static struct cfi_info k5a32xx_topboot_hardcfi = {
-	.cmdset_style	= 2,
-	.total_size	= 0x400000,
-	.nregions	= 2,
-	.regions	= {0x10000, 63, 0x2000, 8},
-	.total_sectors	= 71
-};
-
-static struct flash_idcheck k5a32xx_topboot_idcheck[2] = {
-	{0x00, 0x00EC},
-	{0x02, 0x22A0}
-};
-
-static struct flash_bank_desc k5a32xx_topboot_bankdesc = {
-	0x400000, &k5a32xx_topboot_hardcfi, k5a32xx_topboot_idcheck, 2
-};
-
-/* S{29,71}PL129N device description */
-
-static struct cfi_info pl129n_ce1_hardcfi = {
-	.cmdset_style	= 2,
-	.total_size	= 0x800000,
-	.nregions	= 2,
-	.regions	= {0x10000, 4, 0x40000, 31},
-	.total_sectors	= 35
-};
-
-static struct cfi_info pl129n_ce2_hardcfi = {
-	.cmdset_style	= 2,
-	.total_size	= 0x800000,
-	.nregions	= 2,
-	.regions	= {0x40000, 31, 0x10000, 4},
-	.total_sectors	= 35
-};
-
-static struct flash_idcheck pl129n_idcheck[4] = {
-	{0x00, 0x0001},
-	{0x02, 0x227E},
-	{0x1C, 0x2221},
-	{0x1E, 0x2200}
-};
-
-static struct flash_bank_desc pl129n_banks[2] = {
-	{0x800000, &pl129n_ce1_hardcfi, pl129n_idcheck, 4},
-	{0x800000, &pl129n_ce2_hardcfi, pl129n_idcheck, 4}
-};
-
-/* bank configurations for CFI */
-
-static struct flash_bank_desc cfi_4M_bankdesc = {
-	0x400000, 0, 0, 0
-};
-
-static struct flash_bank_desc cfi_8M_bankdesc = {
-	0x800000, 0, 0, 0
-};
-
-/* list of supported flash devices */
-
-struct flash_device_desc flash_device_list[] = {
-	{"cfi-4M", &cfi_4M_bankdesc, 1},
-	{"cfi-8M", &cfi_8M_bankdesc, 1},
-	{"k5a32xx_t", &k5a32xx_topboot_bankdesc, 1},
-	{"pl129n", pl129n_banks, 2},
-	{0, 0, 0}	/* array terminator */
-};
-
-/* the following variables describe our selected flash device */
-
-struct flash_device_desc *selected_flash_device;
-struct flash_bank_info flash_bank_info[2];
-
-/* called from hwparam.c config file parser */
-void
-set_flash_device(arg, filename_for_errs, lineno_for_errs)
-	char *arg;
-	char *filename_for_errs;
-	int lineno_for_errs;
-{
-	char *cp, *np, *ep;
-	struct flash_device_desc *tp;
-	int bank;
-	struct flash_bank_info *bi;
-
-	if (selected_flash_device) {
-		fprintf(stderr, "%s line %d: duplicate flash setting\n",
-			filename_for_errs, lineno_for_errs);
-		exit(1);
-	}
-	for (cp = arg; isspace(*cp); cp++)
-		;
-	if (!*cp || *cp == '#') {
-too_few_arg:	fprintf(stderr,
-			"%s line %d: flash setting: too few arguments\n",
-			filename_for_errs, lineno_for_errs);
-		exit(1);
-	}
-	for (np = cp; *cp && !isspace(*cp); cp++)
-		;
-	if (*cp)
-		*cp++ = '\0';
-	for (tp = flash_device_list; tp->name; tp++)
-		if (!strcmp(tp->name, np))
-			break;
-	if (!tp->name) {
-		fprintf(stderr,
-			"%s line %d: unknown flash device \"%s\"\n",
-			filename_for_errs, lineno_for_errs, np);
-		exit(1);
-	}
-	selected_flash_device = tp;
-
-	/* now initialize flash_bank_info */
-	for (bank = 0; bank < selected_flash_device->nbanks; bank++) {
-		while (isspace(*cp))
-			cp++;
-		if (!*cp || *cp == '#')
-			goto too_few_arg;
-		for (np = cp; *cp && !isspace(*cp); cp++)
-			;
-		if (*cp)
-			*cp++ = '\0';
-		bi = flash_bank_info + bank;
-		bi->base_addr = strtoul(np, &ep, 16);
-		if (*ep) {
-			fprintf(stderr,
-"%s line %d: syntax error (base addr expected after flash device type)\n",
-				filename_for_errs, lineno_for_errs);
-			exit(1);
-		}
-		/* the rest comes from the flash device type */
-		bi->bank_desc = selected_flash_device->bank_desc + bank;
-		if (bi->base_addr & (bi->bank_desc->align_size - 1)) {
-			fprintf(stderr,
-"%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n",
-				filename_for_errs, lineno_for_errs, bank,
-				(u_long) bi->bank_desc->align_size);
-			exit(1);
-		}
-		bi->cfi = bi->bank_desc->hard_cfi;
-	}
-	while (isspace(*cp))
-		cp++;
-	if (*cp && *cp != '#') {
-		fprintf(stderr,
-			"%s line %d: flash setting: too many arguments\n",
-			filename_for_errs, lineno_for_errs);
-		exit(1);
-	}
-}
-
-flashcmd_blankchk(argc, argv, bank)
-	char **argv;
-{
-	struct flash_bank_info *bi;
-	u_long offset, len;
-	char *strtoul_endp;
-	char *targv[4], targ_start[10], targ_len[10];
-
-	if (argc != 4) {
-inv:		fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n",
-			argv[0], argv[1]);
-		return(-1);
-	}
-	offset = strtoul(argv[2], &strtoul_endp, 16);
-	if (*strtoul_endp)
-		goto inv;
-	if (flash_get_cfi(bank) < 0)
-		return(-1);
-	bi = flash_bank_info + bank;
-	if (offset >= bi->cfi->total_size) {
-		fprintf(stderr,
-		"error: specified offset exceeds flash bank size (0x%lx)\n",
-			(u_long) bi->cfi->total_size);
-		return(-1);
-	}
-	len = strtoul(argv[3], &strtoul_endp, 16);
-	if (*strtoul_endp)
-		goto inv;
-	if (len > bi->cfi->total_size - offset) {
-		fprintf(stderr,
-	"error: specified offset+length exceed flash bank size (0x%lx)\n",
-			(u_long) bi->cfi->total_size);
-		return(-1);
-	}
-	sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset);
-	sprintf(targ_len, "%lx", len);
-	targv[0] = "blankchk";
-	targv[1] = targ_start;
-	targv[2] = targ_len;
-	targv[3] = 0;
-	tpinterf_make_cmd(targv);
-	if (tpinterf_send_cmd() < 0)
-		return(-1);
-	return tpinterf_pass_output(10);	/* 10 s timeout */
-}
-
-flashcmd_dump2file(argc, argv, bank)
-	char **argv;
-{
-	struct flash_bank_info *bi;
-	u_long offset, dumplen, maxlen;
-	char *strtoul_endp;
-	int format;
-
-	if (argc < 3 || argc > 5) {
-inv:		fprintf(stderr, "usage: %s %s outfile [offset [length]]\n",
-			argv[0], argv[1]);
-		return(-1);
-	}
-	if (flash_get_cfi(bank) < 0)
-		return(-1);
-	bi = flash_bank_info + bank;
-	if (argc >= 4) {
-		offset = strtoul(argv[3], &strtoul_endp, 16);
-		if (*strtoul_endp)
-			goto inv;
-		if (offset >= bi->cfi->total_size) {
-			fprintf(stderr,
-		"error: specified offset exceeds flash bank size (0x%lx)\n",
-				(u_long) bi->cfi->total_size);
-			return(-1);
-		}
-	} else
-		offset = 0;
-	maxlen = bi->cfi->total_size - offset;
-	if (argc >= 5) {
-		dumplen = strtoul(argv[4], &strtoul_endp, 16);
-		if (*strtoul_endp)
-			goto inv;
-		if (dumplen > maxlen) {
-			fprintf(stderr,
-	"error: specified offset+length exceed flash bank size (0x%lx)\n",
-				(u_long) bi->cfi->total_size);
-			return(-1);
-		}
-	} else
-		dumplen = maxlen;
-	switch (argv[1][5]) {
-	case 'b':
-		format = 0;
-		break;
-	case 's':
-		format = 1;
-		break;
-	default:
-		fprintf(stderr,
-			"internal bug: bad format in flashcmd_dump2file()\n");
-		return(-1);
-	}
-	return loadtool_memdump(bi->base_addr + offset, dumplen, argv[2],
-				format);
-}
-
-flashcmd_help()
-{
-	return loadtool_help("flash");
-}
-
-flashcmd_info(argc, argv, bank)
-	char **argv;
-{
-	struct flash_bank_info *bi;
-
-	if (argc > 2) {
-		fprintf(stderr, "error: too many arguments\n");
-		return(-1);
-	}
-	bi = flash_bank_info + bank;
-	printf("Flash device type: %s\n", selected_flash_device->name);
-	printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr);
-	if (flash_get_cfi(bank) < 0)
-		return(-1);
-	printf("Bank %d total size: %lx\n", bank, (u_long) bi->cfi->total_size);
-	printf("Sectors in bank %d: %u (%u regions)\n", bank,
-		bi->cfi->total_sectors, bi->cfi->nregions);
-	printf("Command set style: %04X\n", bi->cfi->cmdset_style);
-	flash_id_check(bank, 1);
-	if (selected_flash_device->nbanks == 2 && !bank)
-	    printf("\nFlash device has 2 banks; flash2 command available\n");
-	return(0);
-}
-
-flashcmd_quickprog(argc, argv, bank)
-	char **argv;
-{
-	char *targv[4], targ_base[10];
-	int stat;
-
-	if (flash_get_cfi(bank) < 0)
-		return(-1);
-	if (flash_bank_info[bank].cfi->cmdset_style != 2) {
-		fprintf(stderr,
-"error: this command is currently only implemented for AMD-style flash\n");
-		return(-1);
-	}
-	if (argc != 4) {
-		fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n",
-			argv[0], argv[1]);
-		return(-1);
-	}
-	sprintf(targ_base, "%lx", (u_long) flash_bank_info[bank].base_addr);
-	targv[0] = "AMFB";
-	targv[1] = targ_base;
-	targv[2] = 0;
-	tpinterf_make_cmd(targv);
-	if (tpinterf_send_cmd() < 0)
-		return(-1);
-	stat = tpinterf_pass_output(1);
-	if (stat)
-		return(stat);
-	targv[0] = "AMFW";
-	targv[1] = argv[2];
-	targv[2] = argv[3];
-	targv[3] = 0;
-	if (tpinterf_make_cmd(targv) < 0) {
-		fprintf(stderr, "error: unable to form AMFW target command\n");
-		return(-1);
-	}
-	if (tpinterf_send_cmd() < 0)
-		return(-1);
-	return tpinterf_pass_output(1);
-}
-
-extern int flashcmd_erase();
-extern int flashcmd_progbin();
-extern int flashcmd_program_m0();
-extern int flashcmd_program_srec();
-extern int flashcmd_sectors();
-
-static struct cmdtab {
-	char *cmd;
-	int (*func)();
-} cmdtab[] = {
-	{"blankchk", flashcmd_blankchk},
-	{"dump2bin", flashcmd_dump2file},
-	{"dump2srec", flashcmd_dump2file},
-	{"erase", flashcmd_erase},
-	{"help", flashcmd_help},
-	{"info", flashcmd_info},
-	{"program-bin", flashcmd_progbin},
-	{"program-m0", flashcmd_program_m0},
-	{"program-srec", flashcmd_program_srec},
-	{"quickprog", flashcmd_quickprog},
-	{"sectors", flashcmd_sectors},
-	{0, 0}
-};
-
-cmd_flash(argc, argv)
-	char **argv;
-{
-	int bank;
-	struct cmdtab *tp;
-
-	if (!selected_flash_device) {
-		fprintf(stderr, "No flash configuration defined\n");
-		return(-1);
-	}
-	if (argv[0][5] == '2') {
-		if (selected_flash_device->nbanks < 2) {
-			fprintf(stderr, "Flash device %s has only one bank\n",
-				selected_flash_device->name);
-			return(-1);
-		}
-		bank = 1;
-	} else
-		bank = 0;
-	for (tp = cmdtab; tp->cmd; tp++)
-		if (!strcmp(tp->cmd, argv[1]))
-			break;
-	if (!tp->func) {
-		fprintf(stderr, "%s %s: unknown/unimplemented subcommand\n",
-			argv[0], argv[1]);
-		return(-1);
-	}
-	return tp->func(argc, argv, bank);
-}