diff loadtools/flmisc.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 0dd2c87c1b63
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/flmisc.c	Sat Jun 11 00:13:35 2016 +0000
@@ -0,0 +1,311 @@
+/*
+ * 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);
+	}
+	/* reset flash to read mode */
+	if (bi->ops->reset_cmd(bi) < 0)
+		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);
+	}
+	/* reset flash to read mode */
+	if (bi->ops->reset_cmd(bi) < 0)
+		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 (argc != 4) {
+		fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n",
+			argv[0], argv[1]);
+		return(-1);
+	}
+	if (flash_get_cfi(bank) < 0)
+		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);
+}
+
+flashcmd_reset(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+
+	if (argc > 2) {
+		fprintf(stderr, "error: too many arguments\n");
+		return(-1);
+	}
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	bi = flash_bank_info + bank;
+	return bi->ops->reset_cmd(bi);
+}
+
+flashcmd_status(argc, argv, bank)
+	char **argv;
+{
+	struct flash_bank_info *bi;
+
+	if (argc > 2) {
+		fprintf(stderr, "error: too many arguments\n");
+		return(-1);
+	}
+	if (flash_get_cfi(bank) < 0)
+		return(-1);
+	bi = flash_bank_info + bank;
+	return bi->ops->status_cmd(bi);
+}
+
+flashcmd_unlock(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 (flash_get_cfi(bank) < 0)
+		return(-1);
+	bi = flash_bank_info + bank;
+	if (!bi->ops->needs_unlock) {
+		fprintf(stderr,
+	    "This operation is not applicable to the selected flash type\n");
+		return(-1);
+	}
+	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 (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);
+	printf("Unlocking %d sector(s)\n", endsec - startsec);
+	for (sp = startsec; sp < endsec; sp++) {
+		stat = bi->ops->unlock_sector(bi, sp);
+		if (stat)
+			return(stat);
+		putchar('.');
+		fflush(stdout);
+	}
+	putchar('\n');
+	return(0);
+}