view loadtools/flprogsrec.c @ 506:0dd2c87c1b63

fc-loadtool flash support overhaul
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 28 May 2019 05:12:47 +0000
parents e7502631a0f9
children 97fe41e9242a
line wrap: on
line 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>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "flash.h"
#include "srecreader.h"

extern struct flash_bank_info flash_bank_info[2];

flashcmd_progsrec_gen(bank, imgfile, is_m0)
	char *imgfile;
{
	struct flash_bank_info *bi;
	struct srecreader srr;
	char *targv[4], shortarg[10], longarg[513];
	int resp;
	unsigned long rec_count;

	if (flash_detect(bank, 0) < 0)
		return(-1);
	bi = flash_bank_info + bank;
	srr.filename = imgfile;
	resp = open_srec_file(&srr);
	if (resp < 0)
		return(resp);
	sprintf(shortarg, "%lx", (u_long) bi->base_addr);
	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]);
	tpinterf_make_cmd(targv);
	if (tpinterf_send_cmd() < 0) {
		fclose(srr.openfile);
		return(-1);
	}
	resp = tpinterf_pass_output(1);
	if (resp) {
		fclose(srr.openfile);
		return(resp);
	}
	if (bi->ops->prep_for_program(bi) < 0) {
		fclose(srr.openfile);
		return(-1);
	}
	targv[0] = bi->ops->loadagent_program_cmd;
	targv[1] = shortarg;
	targv[2] = longarg;
	targv[3] = 0;
	for (rec_count = 0; ; ) {
		if (read_s_record(&srr) < 0) {
			/* error msg already printed */
			fclose(srr.openfile);
			return(-1);
		}
		if (srr.record_type == '0') {
			if (srr.lineno == 1)
				continue;
			fprintf(stderr,
	"Warning: S0 record found in line %d of %s (expected in line 1 only)\n",
				srr.lineno, srr.filename);
			continue;
		} else if (srr.record_type == '7')
			break;
		else if (srr.record_type != '3') {
			fprintf(stderr,
		"Warning: unsupported S%c record type in line %d of %s\n",
				srr.record_type, srr.lineno, srr.filename);
			continue;
		}
		/* must be S3 */
		if (s3s7_get_addr_data(&srr) < 0) {
			/* error msg already printed */
			fclose(srr.openfile);
			return(-1);
		}
		if (srr.datalen < 1) {
			fprintf(stderr,
			"%s line %d: S3 record of zero data length ignored\n",
				srr.filename, srr.lineno);
			continue;
		}
		if (srr.addr & 1 || srr.datalen & 1) {
			fprintf(stderr,
			"%s line %d: violates word alignment requirement\n",
				srr.filename, srr.lineno);
			fclose(srr.openfile);
			return(-1);
		}
		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);
			fclose(srr.openfile);
			return(-1);
		}
		if (!rec_count)
		    printf("Programming flash, each \'.\' is 100 S-records\n");
		sprintf(shortarg, "%lx", (u_long) srr.addr);
		build_flashw_hex_string(srr.record + 5, longarg,
					srr.datalen >> 1, is_m0);
		tpinterf_make_cmd(targv);
		if (tpinterf_send_cmd() < 0) {
			fclose(srr.openfile);
			return(-1);
		}
		resp = tpinterf_pass_output(8);	/* 8 s timeout */
		if (resp) {
			fclose(srr.openfile);
			return(resp);
		}
		rec_count++;
		if (rec_count % 100 == 0) {
			putchar('.');
			fflush(stdout);
		}
	}
	/* got S7 */
	fclose(srr.openfile);
	if (!rec_count) {
		fprintf(stderr,
		"%s line %d: S7 without any preceding S3 data records\n",
			srr.filename, srr.lineno);
		return(-1);
	}
	printf("\nProgramming complete\n");
	return(0);
}

flashcmd_program_srec(argc, argv, bank)
	char **argv;
{
	if (argc != 3) {
		fprintf(stderr, "usage: %s %s image.srec\n", argv[0], argv[1]);
		return(-1);
	}
	return flashcmd_progsrec_gen(bank, argv[2], 0);
}

flashcmd_program_m0(argc, argv, bank)
	char **argv;
{
	if (argc != 3) {
		fprintf(stderr, "usage: %s %s image.m0\n", argv[0], argv[1]);
		return(-1);
	}
	return flashcmd_progsrec_gen(bank, argv[2], 1);
}