view loadtools/ltdump.c @ 505:7bf0d909c87e

fc-loadtool flash ID check: change of reset after the check logic This change only affects those flash configurations that have ID checks enabled. The logic for resetting the flash after the ID check has been changed as follows: 1) If the check fails, we return without attempting to reset the flash. 2) If the check is successful, we reset the flash using the configured method (could be AMD or Intel or Intel W30) instead of always doing an AMD flash reset as the original code did.
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 27 May 2019 19:58:01 +0000
parents e7502631a0f9
children 98474043ecdd
line wrap: on
line source

/*
 * This module implements the dump2bin and dump2srec functionality
 * of fc-loadtool.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <time.h>

extern uint32_t crc32_table[];
extern char target_response_line[];

crc32_on_target(area_base, area_len, retptr)
	u_long area_base, area_len, *retptr;
{
	char arg1[10], arg2[10], *argv[4];
	int stat;
	char *strtoul_endp;

	sprintf(arg1, "%lx", area_base);
	sprintf(arg2, "%lx", area_len);
	argv[0] = "crc32";
	argv[1] = arg1;
	argv[2] = arg2;
	argv[3] = 0;
	tpinterf_make_cmd(argv);
	if (tpinterf_send_cmd() < 0)
		return(-1);
	stat = tpinterf_capture_output_oneline(10);	/* 10 s timeout */
	if (stat != 1) {
errout:		fprintf(stderr, "error: malformed response to crc32 command\n");
		return(-1);
	}
	if (strlen(target_response_line) != 8)
		goto errout;
	*retptr = strtoul(target_response_line, &strtoul_endp, 16);
	if (strtoul_endp != target_response_line + 8)
		goto errout;
	return(0);
}

cmd_crc32(argc, argv)
	char **argv;
{
	u_long area_base, area_len;
	char *strtoul_endp;
	u_long crc_result;
	int stat;

	area_base = strtoul(argv[1], &strtoul_endp, 16);
	if (*strtoul_endp) {
inv:		fprintf(stderr, "usage: crc32 hex-start hex-len\n");
		return(-1);
	}
	area_len = strtoul(argv[2], &strtoul_endp, 16);
	if (*strtoul_endp)
		goto inv;
	stat = crc32_on_target(area_base, area_len, &crc_result);
	if (stat == 0)
		printf("%08lX\n", crc_result);
	return(stat);
}

/* the actual dump facility */

static FILE *dump_outfile;
static int dump_save_srec;
static uint32_t dump_nextaddr, dump_crcaccum;
static uint32_t dump_total_len, dump_progress_len;
static u_char dump_binrec[0x86];
static time_t dump_last_time;

static char dumpsrec_s0_line[] = "S007000044554D50C2\n";
static char dumpsrec_s7_line[] = "S70500000000FA\n";

static
dump_receiver(line)
	char *line;
{
	int i, b;
	u_char sr_cksum;
	uint32_t addr_from_srec;
	time_t curtime;

	if (strncmp(line, "S385", 4)) {
		fprintf(stderr,
			"error: target response is not the expected S385...\n");
		return(-1);
	}
	for (i = 0; i < 0x86; i++) {
		b = decode_hex_byte(line + i*2 + 2);
		if (b < 0) {
			fprintf(stderr,
			"data from target: S-record hex decode error\n");
			return(-1);
		}
		dump_binrec[i] = b;
	}
	sr_cksum = 0;
	for (i = 0; i < 0x86; i++)
		sr_cksum += dump_binrec[i];
	if (sr_cksum != 0xFF) {
		fprintf(stderr, "data from target: bad S-record checksum\n");
		return(-1);
	}
	/* basic S-record format OK; now verify the address */
	addr_from_srec = ((uint32_t) dump_binrec[1] << 24) |
			 ((uint32_t) dump_binrec[2] << 16) |
			 ((uint32_t) dump_binrec[3] << 8) |
			  (uint32_t) dump_binrec[4];
	if (addr_from_srec != dump_nextaddr) {
		fprintf(stderr,
			"error: S3 record from target has the wrong address\n");
		return(-1);
	}
	/* all checks passed - save it */
	if (dump_save_srec) {
		if (!dump_progress_len)
			fputs(dumpsrec_s0_line, dump_outfile);
		fprintf(dump_outfile, "%s\n", line);
	} else
		fwrite(dump_binrec + 5, 1, 0x80, dump_outfile);
	/* update running CRC */
	for (i = 0; i < 0x80; i++)
		dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^
						dump_binrec[i+5]] ^
				(dump_crcaccum >> 8);
	/* progress indication */
	dump_progress_len += 0x80;
	i = dump_progress_len * 100 / dump_total_len;
	time(&curtime);
	if (curtime != dump_last_time || i == 100) {
		printf("\rRx %lu out of %lu bytes (%i%%)",
			(u_long) dump_progress_len, (u_long) dump_total_len, i);
		fflush(stdout);
	}
	dump_nextaddr += 0x80;
	dump_last_time = curtime;
	return(1);
}

loadtool_memdump(start_addr, area_len, filename, fmt_srec)
	u_long start_addr, area_len;
	char *filename;
{
	u_long target_crc_init, target_crc_fin;
	char *target_argv[4], target_arg1[10], target_arg2[10];
	int stat;

	if (start_addr & 0x7F || area_len & 0x7F) {
		fprintf(stderr,
		"error: implementation limit: 128-byte alignment required\n");
		return(-1);
	}
	printf("Requesting initial CRC-32 of the area from target...\n");
	stat = crc32_on_target(start_addr, area_len, &target_crc_init);
	if (stat)
		return(stat);
	printf("got %08lX\n", target_crc_init);
	dump_outfile = fopen(filename, "w");
	if (!dump_outfile) {
		perror(filename);
		return(-1);
	}
	dump_save_srec = fmt_srec;
	dump_nextaddr = start_addr;
	dump_crcaccum = 0xFFFFFFFF;
	dump_total_len = area_len;
	dump_progress_len = 0;

	printf("Requesting memory dump...\n");
	sprintf(target_arg1, "%lx", start_addr);
	sprintf(target_arg2, "%lx", area_len);
	target_argv[0] = "DUMP";
	target_argv[1] = target_arg1;
	target_argv[2] = target_arg2;
	target_argv[3] = 0;
	tpinterf_make_cmd(target_argv);
	stat = tpinterf_send_cmd();
	if (stat < 0) {
		fclose(dump_outfile);
		return(stat);
	}
	stat = tpinterf_capture_output(2, dump_receiver);
	if (stat < 0) {
		fclose(dump_outfile);
		return(stat);
	}
	putchar('\n');	/* after last progress line */

	/* sanity checks */
	if (dump_nextaddr != start_addr + area_len) {
		fclose(dump_outfile);
		fprintf(stderr,
		"error: received dump length does not match expected\n");
		return(-1);
	}
	if (dump_crcaccum != (uint32_t) target_crc_init) {
		fclose(dump_outfile);
		fprintf(stderr, "error: CRC mismatch (computed %lX)\n",
			(u_long) dump_crcaccum);
		return(-1);
	}
	if (fmt_srec)
		fputs(dumpsrec_s7_line, dump_outfile);
	fclose(dump_outfile);
	printf("Requesting another CRC-32 of the area from target...\n");
	stat = crc32_on_target(start_addr, area_len, &target_crc_fin);
	if (stat)
		return(stat);
	if (target_crc_fin == target_crc_init) {
		printf("match, dump successful\n");
		return(0);
	} else {
		fprintf(stderr, "mismatch: got %lX this time\n",
			target_crc_fin);
		return(-1);
	}
}

cmd_dump2bin(argc, argv)
	char **argv;
{
	u_long area_base, area_len;
	char *strtoul_endp;

	area_base = strtoul(argv[1], &strtoul_endp, 16);
	if (*strtoul_endp) {
inv:		fprintf(stderr, "usage: dump2bin hex-start hex-len outfile\n");
		return(-1);
	}
	area_len = strtoul(argv[2], &strtoul_endp, 16);
	if (*strtoul_endp)
		goto inv;
	return loadtool_memdump(area_base, area_len, argv[3], 0);
}

cmd_dump2srec(argc, argv)
	char **argv;
{
	u_long area_base, area_len;
	char *strtoul_endp;

	area_base = strtoul(argv[1], &strtoul_endp, 16);
	if (*strtoul_endp) {
inv:		fprintf(stderr, "usage: dump2srec hex-start hex-len outfile\n");
		return(-1);
	}
	area_len = strtoul(argv[2], &strtoul_endp, 16);
	if (*strtoul_endp)
		goto inv;
	return loadtool_memdump(area_base, area_len, argv[3], 1);
}