diff loadtools/flmain.c @ 405:a212b4968b29

fc-loadtool flash: another refactoring: geometry vs. command set
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Tue, 17 Jun 2014 00:33:05 +0000
parents loadtools/ltflash.c@7ceeec049be4
children 0b8e5072abde
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/flmain.c	Tue Jun 17 00:33:05 2014 +0000
@@ -0,0 +1,251 @@
+/*
+ * This module is the main entry point for fc-loadtool flash functions
+ */
+
+#include <sys/types.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}
+};
+
+/* 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;
+
+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},
+	{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_progbin();
+extern int flashcmd_program_m0();
+extern int flashcmd_program_srec();
+extern int flashcmd_quickprog();
+extern int flashcmd_sectors();
+
+static struct cmdtab {
+	char *cmd;
+	int (*func)();
+} cmdtab[] = {
+	{"blankchk", flashcmd_blankchk},
+	{"dump2bin", flashcmd_dump2file},
+	{"dump2srec", flashcmd_dump2file},
+	{"erase", flashcmd_erase},
+	{"help", flashcmd_help},
+	{"info", flashcmd_info},
+	{"program-bin", flashcmd_progbin},
+	{"program-m0", flashcmd_program_m0},
+	{"program-srec", flashcmd_program_srec},
+	{"quickprog", flashcmd_quickprog},
+	{"sectors", flashcmd_sectors},
+	{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);
+}