view loadtools/flmain.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 545e1718f5fb
children 0dd2c87c1b63
line wrap: on
line source

/*
 * This module is the main entry point for fc-loadtool flash functions
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "flash.h"

/* K5A32xx device description */

static struct flash_geom k5a32xx_topboot_geom = {
	.total_size	= 0x400000,
	.nregions	= 2,
	.regions	= {0x10000, 63, 0x2000, 8},
	.total_sectors	= 71,
};

static struct flash_idcheck k5a32xx_topboot_idcheck[2] = {
	{0x00, 0x00EC},
	{0x02, 0x22A0}
};

static struct flash_bank_desc k5a32xx_topboot_bankdesc = {
	0x400000, &k5a32xx_topboot_geom, k5a32xx_topboot_idcheck, 2
};

/* S{29,71}PL129N device description */

static struct flash_geom pl129n_ce1_geom = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x10000, 4, 0x40000, 31},
	.total_sectors	= 35,
};

static struct flash_geom pl129n_ce2_geom = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x40000, 31, 0x10000, 4},
	.total_sectors	= 35,
};

static struct flash_idcheck pl129n_idcheck[4] = {
	{0x00, 0x0001},
	{0x02, 0x227E},
	{0x1C, 0x2221},
	{0x1E, 0x2200}
};

static struct flash_bank_desc pl129n_banks[2] = {
	{0x800000, &pl129n_ce1_geom, pl129n_idcheck, 4},
	{0x800000, &pl129n_ce2_geom, pl129n_idcheck, 4}
};

/* 28F640W30B device description */

static struct flash_geom f640w30b_geom = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x2000, 8, 0x10000, 127},
	.total_sectors	= 135,
};

static struct flash_idcheck f640w30b_idcheck[2] = {
	{0x00, 0x0089},
	{0x02, 0x8855}
};

static struct flash_bank_desc f640w30b_bankdesc = {
	0x800000, &f640w30b_geom, f640w30b_idcheck, 2
};

/* bank configurations for CFI */

static struct flash_bank_desc cfi_4M_bankdesc = {
	0x400000, 0, 0, 0
};

static struct flash_bank_desc cfi_8M_bankdesc = {
	0x800000, 0, 0, 0
};

/* list of supported flash devices */

extern struct flash_cmdset flash_cmdset_amd;
extern struct flash_cmdset flash_cmdset_intel_w30;

struct flash_device_desc flash_device_list[] = {
	{"cfi-4M", &cfi_4M_bankdesc, 1, 0},
	{"cfi-8M", &cfi_8M_bankdesc, 1, 0},
	{"k5a32xx_t", &k5a32xx_topboot_bankdesc, 1, &flash_cmdset_amd},
	{"pl129n", pl129n_banks, 2, &flash_cmdset_amd},
	{"28f640w30b", &f640w30b_bankdesc, 1, &flash_cmdset_intel_w30},
	{0, 0, 0, 0}	/* array terminator */
};

/* the following variables describe our selected flash device */

struct flash_device_desc *selected_flash_device;
struct flash_bank_info flash_bank_info[2];

/* called from hwparam.c config file parser */
void
set_flash_device(arg, filename_for_errs, lineno_for_errs)
	char *arg;
	char *filename_for_errs;
	int lineno_for_errs;
{
	char *cp, *np, *ep;
	struct flash_device_desc *tp;
	int bank;
	struct flash_bank_info *bi;

	if (selected_flash_device) {
		fprintf(stderr, "%s line %d: duplicate flash setting\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
	for (cp = arg; isspace(*cp); cp++)
		;
	if (!*cp || *cp == '#') {
too_few_arg:	fprintf(stderr,
			"%s line %d: flash setting: too few arguments\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	for (tp = flash_device_list; tp->name; tp++)
		if (!strcmp(tp->name, np))
			break;
	if (!tp->name) {
		fprintf(stderr,
			"%s line %d: unknown flash device \"%s\"\n",
			filename_for_errs, lineno_for_errs, np);
		exit(1);
	}
	selected_flash_device = tp;

	/* now initialize flash_bank_info */
	for (bank = 0; bank < selected_flash_device->nbanks; bank++) {
		while (isspace(*cp))
			cp++;
		if (!*cp || *cp == '#')
			goto too_few_arg;
		for (np = cp; *cp && !isspace(*cp); cp++)
			;
		if (*cp)
			*cp++ = '\0';
		bi = flash_bank_info + bank;
		bi->base_addr = strtoul(np, &ep, 16);
		if (*ep) {
			fprintf(stderr,
"%s line %d: syntax error (base addr expected after flash device type)\n",
				filename_for_errs, lineno_for_errs);
			exit(1);
		}
		/* the rest comes from the flash device type */
		bi->bank_desc = selected_flash_device->bank_desc + bank;
		if (bi->base_addr & (bi->bank_desc->align_size - 1)) {
			fprintf(stderr,
"%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n",
				filename_for_errs, lineno_for_errs, bank,
				(u_long) bi->bank_desc->align_size);
			exit(1);
		}
		bi->geom = bi->bank_desc->geom;
		bi->ops = selected_flash_device->cmdset;
	}
	while (isspace(*cp))
		cp++;
	if (*cp && *cp != '#') {
		fprintf(stderr,
			"%s line %d: flash setting: too many arguments\n",
			filename_for_errs, lineno_for_errs);
		exit(1);
	}
}

flashcmd_help()
{
	return loadtool_help("flash");
}

flashcmd_info(argc, argv, bank)
	char **argv;
{
	struct flash_bank_info *bi;

	if (argc > 2) {
		fprintf(stderr, "error: too many arguments\n");
		return(-1);
	}
	bi = flash_bank_info + bank;
	printf("Flash device type: %s\n", selected_flash_device->name);
	printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr);
	if (flash_get_cfi(bank) < 0)
		return(-1);
	printf("Bank %d total size: %lx\n", bank,
		(u_long) bi->geom->total_size);
	printf("Sectors in bank %d: %u (%u regions)\n", bank,
		bi->geom->total_sectors, bi->geom->nregions);
	printf("Command set style: %s\n", bi->ops->cmdset_name);
	flash_id_check(bank, 1);
	if (selected_flash_device->nbanks == 2 && !bank)
	    printf("\nFlash device has 2 banks; flash2 command available\n");
	return(0);
}

extern int flashcmd_blankchk();
extern int flashcmd_dump2file();
extern int flashcmd_erase();
extern int flashcmd_erase_program_boot();
extern int flashcmd_progbin();
extern int flashcmd_program_m0();
extern int flashcmd_program_srec();
extern int flashcmd_quickprog();
extern int flashcmd_reset();
extern int flashcmd_sectors();
extern int flashcmd_status();
extern int flashcmd_unlock();

static struct cmdtab {
	char *cmd;
	int (*func)();
} cmdtab[] = {
	{"blankchk", flashcmd_blankchk},
	{"dump2bin", flashcmd_dump2file},
	{"dump2srec", flashcmd_dump2file},
	{"erase", flashcmd_erase},
	{"erase-program-boot", flashcmd_erase_program_boot},
	{"help", flashcmd_help},
	{"info", flashcmd_info},
	{"program-bin", flashcmd_progbin},
	{"program-m0", flashcmd_program_m0},
	{"program-srec", flashcmd_program_srec},
	{"quickprog", flashcmd_quickprog},
	{"reset", flashcmd_reset},
	{"sectors", flashcmd_sectors},
	{"status", flashcmd_status},
	{"unlock", flashcmd_unlock},
	{0, 0}
};

cmd_flash(argc, argv)
	char **argv;
{
	int bank;
	struct cmdtab *tp;

	if (!selected_flash_device) {
		fprintf(stderr, "No flash configuration defined\n");
		return(-1);
	}
	if (argv[0][5] == '2') {
		if (selected_flash_device->nbanks < 2) {
			fprintf(stderr, "Flash device %s has only one bank\n",
				selected_flash_device->name);
			return(-1);
		}
		bank = 1;
	} else
		bank = 0;
	for (tp = cmdtab; tp->cmd; tp++)
		if (!strcmp(tp->cmd, argv[1]))
			break;
	if (!tp->func) {
		fprintf(stderr, "%s %s: unknown/unimplemented subcommand\n",
			argv[0], argv[1]);
		return(-1);
	}
	return tp->func(argc, argv, bank);
}