view loadtools/flmisc.c @ 619:f82551c77e58

libserial-newlnx: ASYNC_LOW_LATENCY patch reverted Reports from Das Signal indicate that loadtools performance on Debian is about the same as on Slackware, and that including or omitting the ASYNC_LOW_LATENCY patch from Serg makes no difference. Because the patch in question does not appear to be necessary, it is being reverted until and unless someone other than Serg reports an actual real-world system on which loadtools operation times are slowed compared to the Mother's Slackware reference and on which Slackware-like performance can be restored by setting the ASYNC_LOW_LATENCY flag.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 27 Feb 2020 01:09:48 +0000
parents 4be92bcd1535
children cd48bc4c5460
line wrap: on
line source

/*
 * 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 <time.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_detect(bank, 0) < 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_detect(bank, 0) < 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;
	time_t start_time, finish_time;
	unsigned duration, mm, ss;

	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_detect(bank, 0) < 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);
	printf("Erasing %d sector(s)\n", endsec - startsec);
	time(&start_time);
	for (sp = startsec; sp < endsec; sp++) {
		stat = bi->ops->erase_sector(bi, sp);
		if (stat)
			return(stat);
		putchar('.');
		fflush(stdout);
	}
	time(&finish_time);
	putchar('\n');
	duration = finish_time - start_time;
	mm = duration / 60;
	ss = duration - mm * 60;
	printf("Operation completed in %um%us\n", mm, ss);
	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_detect(bank, 0) < 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_detect(bank, 0) < 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_detect(bank, 0) < 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_detect(bank, 0) < 0)
		return(-1);
	bi = flash_bank_info + bank;
	if (!bi->ops->needs_unlock) {
		fprintf(stderr,
		      "This operation is not applicable to AMD-style flash\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);
}