view loadtools/chainload.c @ 1010:1d144553a5d0 default tip

CHANGES: fc-host-tools-r21 about to be released
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 12 Dec 2023 07:45:56 +0000
parents 185c9bf208d3
children
line wrap: on
line source

/*
 * This module implements the chain-loading of XRAM images via loadagent.
 */

#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include "../libserial/baudrate.h"
#include "discontig.h"
#include "srecreader.h"

extern int target_fd;

struct srecreader xramimage;

extern struct baudrate *current_baud_rate;
extern struct baudrate *xram_run_baudrate;
extern int xram_jtag_mode;
extern uint32_t crc32_table[];

perform_chain_load()
{
	int rc, reclen, too_many_regions;
	unsigned long rec_count;
	struct discontig_prog regions[MAX_SREC_REGIONS], *regp;
	unsigned regcount, reg;
	char *argv[3], jumparg[10];
	u_char scratch[3], expect_conf[3];
	time_t start_time, finish_time;
	unsigned duration, mm, ss;
	u_long crc_from_target;
	int i, c;

	if (open_srec_file(&xramimage) < 0)
		exit(1);
	/* enter binary RAM download mode */
	argv[0] = "BINML";
	argv[1] = 0;
	tpinterf_make_cmd(argv);
	if (tpinterf_send_cmd())
		exit(1);
	/* read and send S-record image */
	expect_conf[0] = 0x06;
	regp = regions;
	regcount = 0;
	too_many_regions = 0;
	for (rec_count = 0; ; ) {
		if (read_s_record(&xramimage) < 0)
			exit(1);
		switch (xramimage.record_type) {
		case '0':
			if (xramimage.lineno == 1)
				continue;
			fprintf(stderr,
		"%s: S0 record found in line %d (expected in line 1 only)\n",
				xramimage.filename, xramimage.lineno);
			exit(1);
		case '3':
		case '7':
			if (s3s7_get_addr_data(&xramimage) < 0)
				exit(1);
			break;
		default:
			fprintf(stderr,
				"%s line %d: S%c record type not supported\n",
				xramimage.filename, xramimage.lineno,
				xramimage.record_type);
			exit(1);
		}
		if (xramimage.record_type == '7')
			break;
		/* must be S3 */
		if (xramimage.datalen < 1) {
			fprintf(stderr,
				"%s line %d: S3 record has zero data length\n",
				xramimage.filename, xramimage.lineno);
			exit(1);
		}
		if (!rec_count) {
			printf("Each \'.\' is %d S-records\n",
				current_baud_rate->xram_records);
			time(&start_time);
		}
		reclen = xramimage.datalen + 6;
		if (write(target_fd, xramimage.record, reclen) != reclen) {
			perror("binary write to target");
			exit(1);
		}
		rec_count++;
		/* discontiguous regions and CRC-32 accumulation */
		if (!regcount) {
			regp->start = xramimage.addr;
			regp->end = xramimage.addr;
			regp->crc = 0xFFFFFFFF;
			regcount = 1;
		}
		if (xramimage.addr != regp->end) {
			if (regcount >= MAX_SREC_REGIONS)
				too_many_regions = 1;
			else {
				regp++;
				regcount++;
				regp->start = xramimage.addr;
				regp->end = xramimage.addr;
				regp->crc = 0xFFFFFFFF;
			}
		}
		if (!too_many_regions) {
			for (i = 0; i < xramimage.datalen; i++) {
				c = xramimage.record[i+5];
				regp->crc = crc32_table[regp->crc & 0xFF ^ c]
					^ (regp->crc >> 8);
			}
			regp->end += xramimage.datalen;
		}
		/* target sync and progress indication */
		if (rec_count % current_baud_rate->xram_records == 0) {
			scratch[0] = 0x05;	/* ENQ */
			write(target_fd, scratch, 1);
			if (collect_binblock_from_target(scratch, 3, 1))
				exit(1);
			expect_conf[1] = rec_count >> 8;
			expect_conf[2] = rec_count;
			if (bcmp(scratch, expect_conf, 3)) {
				fprintf(stderr,
					"error: expected sync mismatch\n");
				exit(1);
			}
			putchar('.');
			fflush(stdout);
		}
	}
	/* got S7 */
	fclose(xramimage.openfile);
	if (!rec_count) {
		fprintf(stderr,
		"%s line %d: S7 without any preceding S3 data records\n",
			xramimage.filename, xramimage.lineno);
		exit(1);
	}
	putchar('\n');	/* newline after the dots */
	scratch[0] = 0x04;	/* EOT */
	write(target_fd, scratch, 1);
	if (collect_binblock_from_target(scratch, 1, 1))
		exit(1);
	time(&finish_time);
	if (scratch[0] != '=') {
		fprintf(stderr, "error: \'=\' not received as expected\n");
		exit(1);
	}
	duration = finish_time - start_time;
	mm = duration / 60;
	ss = duration - mm * 60;
	printf("XRAM image transferred in %um%02us\n", mm, ss);
	printf("Verifying CRC-32 of %u downloaded region(s)\n", regcount);
	for (reg = 0, regp = regions; reg < regcount; reg++, regp++) {
		rc = crc32_on_target((u_long) regp->start,
				     (u_long) (regp->end - regp->start),
				     &crc_from_target);
		if (rc < 0)
			exit(1);
		if (crc_from_target != regp->crc) {
			fprintf(stderr, "error: CRC mismatch!\n");
			exit(1);
		}
		putchar('.');
		fflush(stdout);
	}
	putchar('\n');
	if (xram_run_baudrate != current_baud_rate) {
		rc = loadagent_switch_baud(xram_run_baudrate);
		if (rc)
			exit(1);
	}
	if (xram_jtag_mode) {
		printf(
      "Leaving target in loadagent for JTAG; image start address is 0x%08lX\n",
			(u_long) xramimage.addr);
		exit(0);
	}
	printf("Sending jump command\n");
	sprintf(jumparg, "%lX", (u_long) xramimage.addr);
	argv[0] = "jump";
	argv[1] = jumparg;
	argv[2] = 0;
	tpinterf_make_cmd(argv);
	if (tpinterf_send_cmd())
		exit(1);
	printf("Sent \"%s %s\": XRAM image should now be running!\n",
		argv[0], argv[1]);
	return(0);
}