# HG changeset patch # User Michael Spacefalcon # Date 1402965185 0 # Node ID a212b4968b29d07c092903328c3ea0f5fe24ba29 # Parent 7daea247606222974bf256c1127a784955931a3e fc-loadtool flash: another refactoring: geometry vs. command set diff -r 7daea2476062 -r a212b4968b29 loadtools/Makefile --- a/loadtools/Makefile Mon Jun 16 01:15:17 2014 +0000 +++ b/loadtools/Makefile Tue Jun 17 00:33:05 2014 +0000 @@ -8,11 +8,11 @@ IRAM_OBJS= defpath.o hexdecode.o hwparam.o hwparamstubs.o romload.o \ sercomm.o sertool.o srecreader.o ttypassthru.o ${EXTRA_OBJ} -LOADTOOL_OBJS= crc32tab.o defpath.o flerase.o flprogbin.o flprogsrec.o \ - flutil.o hexdecode.o hwparam.o labaud.o ltdispatch.o ltdump.o \ - ltexit.o ltflash.o lthelp.o ltmain.o ltmisc.o ltpassthru.o \ - ltscript.o romload.o sercomm.o srecreader.o tpinterf.o \ - tpinterf2.o tpinterf3.o ${EXTRA_OBJ} +LOADTOOL_OBJS= crc32tab.o defpath.o flashops.o flmain.o flmisc.o flprogbin.o \ + flprogsrec.o flutil.o hexdecode.o hwparam.o labaud.o \ + ltdispatch.o ltdump.o ltexit.o lthelp.o ltmain.o ltmisc.o \ + ltpassthru.o ltscript.o romload.o sercomm.o srecreader.o \ + tpinterf.o tpinterf2.o tpinterf3.o ${EXTRA_OBJ} XRAM_OBJS= chainload.o clmain.o defpath.o hexdecode.o hwparam.o \ hwparamstubs.o initscript.o labaud.o romload.o sercomm.o \ diff -r 7daea2476062 -r a212b4968b29 loadtools/flash.h --- a/loadtools/flash.h Mon Jun 16 01:15:17 2014 +0000 +++ b/loadtools/flash.h Tue Jun 17 00:33:05 2014 +0000 @@ -14,9 +14,11 @@ #define CFI_MAX_REGIONS 4 -/* The info in struct cfi_info can be either gathered from CFI or hard-coded. */ -struct cfi_info { - uint16_t cmdset_style; +/* + * The info in struct flash_geom can be either + * gathered from CFI or hard-coded. + */ +struct flash_geom { uint32_t total_size; unsigned nregions; struct flash_region_desc regions[CFI_MAX_REGIONS]; @@ -30,7 +32,7 @@ struct flash_bank_desc { uint32_t align_size; - struct cfi_info *hard_cfi; + struct flash_geom *geom; struct flash_idcheck *idcheck_table; unsigned idcheck_num; }; @@ -39,6 +41,7 @@ char *name; struct flash_bank_desc *bank_desc; unsigned nbanks; + struct flash_cmdset *cmdset; }; /* the following structures describe flash banks as accessible to us */ @@ -48,10 +51,22 @@ uint32_t size; }; +struct flash_cmdset { + char *cmdset_name; + int (*reset_cmd)(); + int (*status_cmd)(); + int (*unlock_sector)(); + int (*erase_sector)(); + int (*prep_for_program)(); + char *loadagent_setbase_cmd; + char *loadagent_program_cmd; +}; + struct flash_bank_info { uint32_t base_addr; struct flash_bank_desc *bank_desc; - struct cfi_info *cfi; + struct flash_geom *geom; + struct flash_cmdset *ops; struct sector_info *sectors; int idcheck_done; }; diff -r 7daea2476062 -r a212b4968b29 loadtools/flashops.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/flashops.c Tue Jun 17 00:33:05 2014 +0000 @@ -0,0 +1,95 @@ +/* + * This module implements those flash operations which are dependent + * on the AMD vs. Intel command set style. + */ + +#include +#include +#include +#include +#include +#include "flash.h" + +/* common stub functions */ + +static +noop() +{ + return(0); +} + +static +invalid() +{ + fprintf(stderr, + "This operation is not applicable to the selected flash type\n"); + return(-1); +} + +/* AMD flash functions */ + +amd_reset_cmd(bi) + struct flash_bank_info *bi; +{ + if (do_w16(bi->base_addr + 0xAAA, 0xF0)) { + fprintf(stderr, + "unexpected response to w16 when resetting flash to read mode!\n"); + return(-1); + } + return(0); +} + +amd_sector_erase(bi, sp) + struct flash_bank_info *bi; + struct sector_info *sp; +{ + int stat; + uint16_t flstat; + time_t start_time, curtime; + + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA); + if (stat) { +bad_w16: fprintf(stderr, + "unexpected response to w16 in erase cmd sequence - aborting\n"); + return(-1); + } + stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x80); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x30); + if (stat) + goto bad_w16; + start_time = time(0); + for (;;) { + stat = do_r16(bi->base_addr + sp->start, &flstat); + if (stat) + return(stat); /* error msg already printed */ + if (flstat == 0xFFFF) + return(0); + curtime = time(0); + if (curtime >= start_time + 20) { + fprintf(stderr, "erase timeout, aborting\n"); + return(-1); + } + } +} + +struct flash_cmdset flash_cmdset_amd = { + .cmdset_name = "AMD", + .reset_cmd = amd_reset_cmd, + .status_cmd = invalid, + .unlock_sector = invalid, + .erase_sector = amd_sector_erase, + .prep_for_program = noop, + .loadagent_setbase_cmd = "AMFB", + .loadagent_program_cmd = "AMFW", +}; diff -r 7daea2476062 -r a212b4968b29 loadtools/flerase.c --- a/loadtools/flerase.c Mon Jun 16 01:15:17 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * This module implements the flash erase operation - */ - -#include -#include -#include -#include -#include -#include "flash.h" - -extern struct flash_bank_info flash_bank_info[2]; - -do_sector_erase(bi, sp) - struct flash_bank_info *bi; - struct sector_info *sp; -{ - int stat; - uint16_t flstat; - time_t start_time, curtime; - - stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA); - if (stat) { -bad_w16: fprintf(stderr, - "unexpected response to w16 in erase cmd sequence - aborting\n"); - return(-1); - } - stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55); - if (stat) - goto bad_w16; - stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x80); - if (stat) - goto bad_w16; - stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA); - if (stat) - goto bad_w16; - stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55); - if (stat) - goto bad_w16; - stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x30); - if (stat) - goto bad_w16; - start_time = time(0); - for (;;) { - stat = do_r16(bi->base_addr + sp->start, &flstat); - if (stat) - return(stat); /* error msg already printed */ - if (flstat == 0xFFFF) - return(0); - curtime = time(0); - if (curtime >= start_time + 20) { - fprintf(stderr, "erase timeout, aborting\n"); - return(-1); - } - } -} - -flashcmd_erase(argc, argv, bank) - char **argv; -{ - struct flash_bank_info *bi; - u_long offset, len; - char *strtoul_endp; - struct sector_info *startsec, *endsec, *sp; - int stat; - - if (argc != 4) { -inv: fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n", - argv[0], argv[1]); - return(-1); - } - offset = strtoul(argv[2], &strtoul_endp, 16); - if (*strtoul_endp) - goto inv; - if (flash_get_cfi(bank) < 0) - return(-1); - bi = flash_bank_info + bank; - if (bi->cfi->cmdset_style != 2) { - fprintf(stderr, -"error: this command is currently only implemented for AMD-style flash\n"); - return(-1); - } - if (offset >= bi->cfi->total_size) { - fprintf(stderr, - "error: specified offset exceeds flash bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); - return(-1); - } - len = strtoul(argv[3], &strtoul_endp, 16); - if (*strtoul_endp) - goto inv; - if (len > bi->cfi->total_size - offset) { - fprintf(stderr, - "error: specified offset+length exceed flash bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); - return(-1); - } - if (!len) { - printf("Zero length specified - nothing to do!\n"); - return(0); - } - /* now enforce sector alignment for both offset and length */ - if (get_flash_sector_table(bank) < 0) - return(-1); - if (get_flash_sector_range(bi, offset, len, &startsec, &endsec) < 0) - return(-1); - stat = flash_id_check(bank, 0); - if (stat) - return(stat); - printf("Erasing %d sector(s)\n", endsec - startsec); - for (sp = startsec; sp < endsec; sp++) { - stat = do_sector_erase(bi, sp); - if (stat) - return(stat); - putchar('.'); - fflush(stdout); - } - putchar('\n'); - return(0); -} diff -r 7daea2476062 -r a212b4968b29 loadtools/flmain.c --- /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 +#include +#include +#include +#include +#include +#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); +} diff -r 7daea2476062 -r a212b4968b29 loadtools/flmisc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/flmisc.c Tue Jun 17 00:33:05 2014 +0000 @@ -0,0 +1,214 @@ +/* + * Miscellaneous flash commands (fc-loadtool) are implemented here + */ + +#include +#include +#include +#include +#include +#include +#include "flash.h" + +extern struct flash_bank_info flash_bank_info[2]; + +flashcmd_blankchk(argc, argv, bank) + char **argv; +{ + struct flash_bank_info *bi; + u_long offset, len; + char *strtoul_endp; + char *targv[4], targ_start[10], targ_len[10]; + + if (argc != 4) { +inv: fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n", + argv[0], argv[1]); + return(-1); + } + offset = strtoul(argv[2], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + if (flash_get_cfi(bank) < 0) + return(-1); + bi = flash_bank_info + bank; + if (offset >= bi->geom->total_size) { + fprintf(stderr, + "error: specified offset exceeds flash bank size (0x%lx)\n", + (u_long) bi->geom->total_size); + return(-1); + } + len = strtoul(argv[3], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + if (len > bi->geom->total_size - offset) { + fprintf(stderr, + "error: specified offset+length exceed flash bank size (0x%lx)\n", + (u_long) bi->geom->total_size); + return(-1); + } + sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset); + sprintf(targ_len, "%lx", len); + targv[0] = "blankchk"; + targv[1] = targ_start; + targv[2] = targ_len; + targv[3] = 0; + tpinterf_make_cmd(targv); + if (tpinterf_send_cmd() < 0) + return(-1); + return tpinterf_pass_output(10); /* 10 s timeout */ +} + +flashcmd_dump2file(argc, argv, bank) + char **argv; +{ + struct flash_bank_info *bi; + u_long offset, dumplen, maxlen; + char *strtoul_endp; + int format; + + if (argc < 3 || argc > 5) { +inv: fprintf(stderr, "usage: %s %s outfile [offset [length]]\n", + argv[0], argv[1]); + return(-1); + } + if (flash_get_cfi(bank) < 0) + return(-1); + bi = flash_bank_info + bank; + if (argc >= 4) { + offset = strtoul(argv[3], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + if (offset >= bi->geom->total_size) { + fprintf(stderr, + "error: specified offset exceeds flash bank size (0x%lx)\n", + (u_long) bi->geom->total_size); + return(-1); + } + } else + offset = 0; + maxlen = bi->geom->total_size - offset; + if (argc >= 5) { + dumplen = strtoul(argv[4], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + if (dumplen > maxlen) { + fprintf(stderr, + "error: specified offset+length exceed flash bank size (0x%lx)\n", + (u_long) bi->geom->total_size); + return(-1); + } + } else + dumplen = maxlen; + switch (argv[1][5]) { + case 'b': + format = 0; + break; + case 's': + format = 1; + break; + default: + fprintf(stderr, + "internal bug: bad format in flashcmd_dump2file()\n"); + return(-1); + } + return loadtool_memdump(bi->base_addr + offset, dumplen, argv[2], + format); +} + +flashcmd_erase(argc, argv, bank) + char **argv; +{ + struct flash_bank_info *bi; + u_long offset, len; + char *strtoul_endp; + struct sector_info *startsec, *endsec, *sp; + int stat; + + if (argc != 4) { +inv: fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n", + argv[0], argv[1]); + return(-1); + } + offset = strtoul(argv[2], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + if (flash_get_cfi(bank) < 0) + return(-1); + bi = flash_bank_info + bank; + if (offset >= bi->geom->total_size) { + fprintf(stderr, + "error: specified offset exceeds flash bank size (0x%lx)\n", + (u_long) bi->geom->total_size); + return(-1); + } + len = strtoul(argv[3], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + if (len > bi->geom->total_size - offset) { + fprintf(stderr, + "error: specified offset+length exceed flash bank size (0x%lx)\n", + (u_long) bi->geom->total_size); + return(-1); + } + if (!len) { + printf("Zero length specified - nothing to do!\n"); + return(0); + } + /* now enforce sector alignment for both offset and length */ + if (get_flash_sector_table(bank) < 0) + return(-1); + if (get_flash_sector_range(bi, offset, len, &startsec, &endsec) < 0) + return(-1); + stat = flash_id_check(bank, 0); + if (stat) + return(stat); + printf("Erasing %d sector(s)\n", endsec - startsec); + for (sp = startsec; sp < endsec; sp++) { + stat = bi->ops->erase_sector(bi, sp); + if (stat) + return(stat); + putchar('.'); + fflush(stdout); + } + putchar('\n'); + return(0); +} + +flashcmd_quickprog(argc, argv, bank) + char **argv; +{ + struct flash_bank_info *bi; + char *targv[4], targ_base[10]; + int stat; + + if (flash_get_cfi(bank) < 0) + return(-1); + if (argc != 4) { + fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n", + argv[0], argv[1]); + return(-1); + } + bi = flash_bank_info + bank; + sprintf(targ_base, "%lx", (u_long) bi->base_addr); + targv[0] = bi->ops->loadagent_setbase_cmd; + targv[1] = targ_base; + targv[2] = 0; + tpinterf_make_cmd(targv); + if (tpinterf_send_cmd() < 0) + return(-1); + stat = tpinterf_pass_output(1); + if (stat) + return(stat); + targv[0] = bi->ops->loadagent_program_cmd; + targv[1] = argv[2]; + targv[2] = argv[3]; + targv[3] = 0; + if (tpinterf_make_cmd(targv) < 0) { + fprintf(stderr, + "error: unable to form AMFW/INFW target command\n"); + return(-1); + } + if (tpinterf_send_cmd() < 0) + return(-1); + return tpinterf_pass_output(1); +} diff -r 7daea2476062 -r a212b4968b29 loadtools/flprogbin.c --- a/loadtools/flprogbin.c Mon Jun 16 01:15:17 2014 +0000 +++ b/loadtools/flprogbin.c Tue Jun 17 00:33:05 2014 +0000 @@ -1,5 +1,5 @@ /* - * In this module we are going to implement the flash program-bin command: + * This module implements the flash program-bin command: * programming flash using a binary file as the data source. */ @@ -38,15 +38,10 @@ if (flash_get_cfi(bank) < 0) return(-1); bi = flash_bank_info + bank; - if (bi->cfi->cmdset_style != 2) { - fprintf(stderr, -"error: this command is currently only implemented for AMD-style flash\n"); - return(-1); - } - if (flashoff >= bi->cfi->total_size) { + if (flashoff >= bi->geom->total_size) { fprintf(stderr, "error: specified flash offset exceeds bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); + (u_long) bi->geom->total_size); return(-1); } if (flashoff & 1) { @@ -97,10 +92,10 @@ fclose(binf); return(0); } - if (len > bi->cfi->total_size - flashoff) { + if (len > bi->geom->total_size - flashoff) { fprintf(stderr, "error: specified flash offset+length exceed bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); + (u_long) bi->geom->total_size); fclose(binf); return(-1); } @@ -116,7 +111,7 @@ return(-1); } sprintf(shortarg, "%lx", (u_long) bi->base_addr); - targv[0] = "AMFB"; + 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]); @@ -131,7 +126,7 @@ return(cc); } fseek(binf, fileoff, SEEK_SET); - targv[0] = "AMFW"; + targv[0] = bi->ops->loadagent_program_cmd; targv[1] = shortarg; targv[2] = longarg; targv[3] = 0; diff -r 7daea2476062 -r a212b4968b29 loadtools/flprogsrec.c --- a/loadtools/flprogsrec.c Mon Jun 16 01:15:17 2014 +0000 +++ b/loadtools/flprogsrec.c Tue Jun 17 00:33:05 2014 +0000 @@ -1,7 +1,6 @@ /* - * In this module we are going to implement the flash program-srec and - * flash program-m0 commands: programming flash using S-record files - * as the data source. + * This module implements the flash program-srec and flash program-m0 commands: + * programming flash using S-record files as the data source. */ #include @@ -25,11 +24,6 @@ if (flash_get_cfi(bank) < 0) return(-1); bi = flash_bank_info + bank; - if (bi->cfi->cmdset_style != 2) { - fprintf(stderr, -"error: this command is currently only implemented for AMD-style flash\n"); - return(-1); - } srr.filename = imgfile; resp = open_srec_file(&srr); if (resp < 0) @@ -40,7 +34,7 @@ return(resp); } sprintf(shortarg, "%lx", (u_long) bi->base_addr); - targv[0] = "AMFB"; + 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]); @@ -54,7 +48,7 @@ fclose(srr.openfile); return(resp); } - targv[0] = "AMFW"; + targv[0] = bi->ops->loadagent_program_cmd; targv[1] = shortarg; targv[2] = longarg; targv[3] = 0; @@ -98,8 +92,8 @@ fclose(srr.openfile); return(-1); } - srr.addr &= bi->cfi->total_size - 1; - if (srr.addr + srr.datalen > bi->cfi->total_size) { + 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); diff -r 7daea2476062 -r a212b4968b29 loadtools/flutil.c --- a/loadtools/flutil.c Mon Jun 16 01:15:17 2014 +0000 +++ b/loadtools/flutil.c Tue Jun 17 00:33:05 2014 +0000 @@ -9,6 +9,8 @@ #include "flash.h" extern struct flash_bank_info flash_bank_info[2]; +extern struct flash_cmdset flash_cmdset_amd; +extern struct flash_cmdset flash_cmdset_intel; static int cfi_read_byte(bi, off, ret16p) @@ -37,29 +39,17 @@ return(0); } -static int -cfi_id_return_to_read_mode(bi) - struct flash_bank_info *bi; -{ - if (do_w16(bi->base_addr + 0xAAA, 0xF0)) { - fprintf(stderr, - "unexpected response to w16 when resetting flash to read mode!\n"); - return(-1); - } - return(0); -} - flash_get_cfi(bank) { struct flash_bank_info *bi; - struct cfi_info *cfi; + struct flash_geom *geom; struct flash_region_desc *reg; int nr; - uint16_t rdval; + uint16_t rdval, cmdset_id; uint32_t size_check; bi = flash_bank_info + bank; - if (bi->cfi) + if (bi->geom) return(0); printf("Performing CFI query\n"); if (do_w16(bi->base_addr + 0xAA, 0x98)) { @@ -71,7 +61,7 @@ return(-1); if (rdval != 'Q') { noqry: fprintf(stderr, "error: no QRY response from flash\n"); - cfi_id_return_to_read_mode(bi); + amd_reset_cmd(bi); return(-1); } if (cfi_read_byte(bi, 0x11, &rdval) < 0) @@ -82,35 +72,52 @@ return(-1); if (rdval != 'Y') goto noqry; - cfi = malloc(sizeof(struct cfi_info)); - if (!cfi) { + if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0) + return(-1); + if (!bi->ops) { + switch (cmdset_id) { + case 2: + bi->ops = &flash_cmdset_amd; + break; +#if 0 + case 3: + bi->ops = &flash_cmdset_intel; + break; +#endif + default: + fprintf(stderr, "error: command set %04X unsupported\n", + cmdset_id); + amd_reset_cmd(bi); + return(-1); + } + } + geom = malloc(sizeof(struct flash_geom)); + if (!geom) { fprintf(stderr, - "unable to malloc buffer for flash bank %d CFI structure\n", + "unable to malloc buffer for flash bank %d CFI geometry structure\n", bank); - cfi_id_return_to_read_mode(bi); - return(-1); - } - if (cfi_read_twobyte(bi, 0x13, &cfi->cmdset_style) < 0) { -free_and_immed_out: - free(cfi); + bi->ops->reset_cmd(bi); return(-1); } /* total device size */ - if (cfi_read_byte(bi, 0x27, &rdval) < 0) - goto free_and_immed_out; + if (cfi_read_byte(bi, 0x27, &rdval) < 0) { +free_and_immed_out: + free(geom); + return(-1); + } if (rdval < 20 || rdval > 24) { fprintf(stderr, "error: CFI reports unreasonable device size\n"); free_and_clean_out: - free(cfi); - cfi_id_return_to_read_mode(bi); + free(geom); + bi->ops->reset_cmd(bi); return(-1); } - cfi->total_size = 1 << rdval; - if (cfi->total_size > bi->bank_desc->align_size) { + geom->total_size = 1 << rdval; + if (geom->total_size > bi->bank_desc->align_size) { fprintf(stderr, "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", - (u_long) cfi->total_size, bi->bank_desc->align_size); + (u_long) geom->total_size, bi->bank_desc->align_size); goto free_and_clean_out; } if (cfi_read_byte(bi, 0x2C, &rdval) < 0) @@ -120,11 +127,11 @@ "error: CFI reports unreasonable # of erase regions\n"); goto free_and_clean_out; } - cfi->nregions = rdval; - cfi->total_sectors = 0; + geom->nregions = rdval; + geom->total_sectors = 0; size_check = 0; - for (nr = 0; nr < cfi->nregions; nr++) { - reg = cfi->regions + nr; + for (nr = 0; nr < geom->nregions; nr++) { + reg = geom->regions + nr; if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0) goto free_and_immed_out; if (rdval > 255) { @@ -134,7 +141,7 @@ goto free_and_clean_out; } reg->nsectors = rdval + 1; - cfi->total_sectors += reg->nsectors; + geom->total_sectors += reg->nsectors; if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0) goto free_and_immed_out; if (rdval < 0x20 || rdval > 0x400) { @@ -146,31 +153,30 @@ reg->sector_size = rdval << 8; size_check += reg->sector_size * reg->nsectors; } - if (cfi_id_return_to_read_mode(bi) < 0) { + if (bi->ops->reset_cmd(bi) < 0) { /* error msg already printed */ - free(cfi); + free(geom); return(-1); } - if (size_check != cfi->total_size) { + if (size_check != geom->total_size) { fprintf(stderr, "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n", - (u_long) size_check, (u_long) cfi->total_size); - free(cfi); + (u_long) size_check, (u_long) geom->total_size); + free(geom); return(-1); } /* all checks passed */ - bi->cfi = cfi; + bi->geom = geom; printf( -"CFI query successful: total size %lx, %u sectors, command set style %04X\n\n", - (u_long) cfi->total_size, cfi->total_sectors, - cfi->cmdset_style); +"CFI query successful: total size %lx, %u sectors, command set style %04X\n", + (u_long) geom->total_size, geom->total_sectors, cmdset_id); return(1); } get_flash_sector_table(bank) { struct flash_bank_info *bi; - struct cfi_info *cfi; + struct flash_geom *geom; struct flash_region_desc *reg; struct sector_info *sp; uint32_t offset; @@ -182,9 +188,9 @@ i = flash_get_cfi(bank); if (i < 0) return(i); - cfi = bi->cfi; + geom = bi->geom; sp = (struct sector_info *) malloc(sizeof(struct sector_info) - * (cfi->total_sectors + 1)); + * (geom->total_sectors + 1)); if (!sp) { fprintf(stderr, "unable to malloc buffer for flash bank %d sector table\n", @@ -194,8 +200,8 @@ bi->sectors = sp; /* now fill it */ offset = 0; - for (nr = 0; nr < cfi->nregions; nr++) { - reg = cfi->regions + nr; + for (nr = 0; nr < geom->nregions; nr++) { + reg = geom->regions + nr; for (i = 0; i < reg->nsectors; i++) { sp->start = offset; sp->size = reg->sector_size; @@ -204,12 +210,12 @@ } } /* sanity checks */ - if (sp - bi->sectors != cfi->total_sectors) { + if (sp - bi->sectors != geom->total_sectors) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong # of sectors at the end\n"); abort(); } - if (offset != cfi->total_size) { + if (offset != geom->total_size) { fprintf(stderr, "BUG in get_flash_sector_table(): wrong offset at the end\n"); abort(); @@ -233,7 +239,7 @@ if (get_flash_sector_table(bank) < 0) return(-1); bi = flash_bank_info + bank; - printf("%u sectors in flash bank %d:\n", bi->cfi->total_sectors, bank); + printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank); printf("Offset Size\n"); for (sp = bi->sectors; sp->size; sp++) printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size); diff -r 7daea2476062 -r a212b4968b29 loadtools/ltflash.c --- a/loadtools/ltflash.c Mon Jun 16 01:15:17 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,392 +0,0 @@ -/* - * This module contains the "core" of fc-loadtool flash operations; - * fl*.c modules contain the rest. - */ - -#include -#include -#include -#include -#include -#include -#include "flash.h" - -/* K5A32xx device description */ - -static struct cfi_info k5a32xx_topboot_hardcfi = { - .cmdset_style = 2, - .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_hardcfi, k5a32xx_topboot_idcheck, 2 -}; - -/* S{29,71}PL129N device description */ - -static struct cfi_info pl129n_ce1_hardcfi = { - .cmdset_style = 2, - .total_size = 0x800000, - .nregions = 2, - .regions = {0x10000, 4, 0x40000, 31}, - .total_sectors = 35 -}; - -static struct cfi_info pl129n_ce2_hardcfi = { - .cmdset_style = 2, - .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_hardcfi, pl129n_idcheck, 4}, - {0x800000, &pl129n_ce2_hardcfi, 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 */ - -struct flash_device_desc flash_device_list[] = { - {"cfi-4M", &cfi_4M_bankdesc, 1}, - {"cfi-8M", &cfi_8M_bankdesc, 1}, - {"k5a32xx_t", &k5a32xx_topboot_bankdesc, 1}, - {"pl129n", pl129n_banks, 2}, - {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->cfi = bi->bank_desc->hard_cfi; - } - 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_blankchk(argc, argv, bank) - char **argv; -{ - struct flash_bank_info *bi; - u_long offset, len; - char *strtoul_endp; - char *targv[4], targ_start[10], targ_len[10]; - - if (argc != 4) { -inv: fprintf(stderr, "usage: %s %s hex-start-offset hex-length\n", - argv[0], argv[1]); - return(-1); - } - offset = strtoul(argv[2], &strtoul_endp, 16); - if (*strtoul_endp) - goto inv; - if (flash_get_cfi(bank) < 0) - return(-1); - bi = flash_bank_info + bank; - if (offset >= bi->cfi->total_size) { - fprintf(stderr, - "error: specified offset exceeds flash bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); - return(-1); - } - len = strtoul(argv[3], &strtoul_endp, 16); - if (*strtoul_endp) - goto inv; - if (len > bi->cfi->total_size - offset) { - fprintf(stderr, - "error: specified offset+length exceed flash bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); - return(-1); - } - sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset); - sprintf(targ_len, "%lx", len); - targv[0] = "blankchk"; - targv[1] = targ_start; - targv[2] = targ_len; - targv[3] = 0; - tpinterf_make_cmd(targv); - if (tpinterf_send_cmd() < 0) - return(-1); - return tpinterf_pass_output(10); /* 10 s timeout */ -} - -flashcmd_dump2file(argc, argv, bank) - char **argv; -{ - struct flash_bank_info *bi; - u_long offset, dumplen, maxlen; - char *strtoul_endp; - int format; - - if (argc < 3 || argc > 5) { -inv: fprintf(stderr, "usage: %s %s outfile [offset [length]]\n", - argv[0], argv[1]); - return(-1); - } - if (flash_get_cfi(bank) < 0) - return(-1); - bi = flash_bank_info + bank; - if (argc >= 4) { - offset = strtoul(argv[3], &strtoul_endp, 16); - if (*strtoul_endp) - goto inv; - if (offset >= bi->cfi->total_size) { - fprintf(stderr, - "error: specified offset exceeds flash bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); - return(-1); - } - } else - offset = 0; - maxlen = bi->cfi->total_size - offset; - if (argc >= 5) { - dumplen = strtoul(argv[4], &strtoul_endp, 16); - if (*strtoul_endp) - goto inv; - if (dumplen > maxlen) { - fprintf(stderr, - "error: specified offset+length exceed flash bank size (0x%lx)\n", - (u_long) bi->cfi->total_size); - return(-1); - } - } else - dumplen = maxlen; - switch (argv[1][5]) { - case 'b': - format = 0; - break; - case 's': - format = 1; - break; - default: - fprintf(stderr, - "internal bug: bad format in flashcmd_dump2file()\n"); - return(-1); - } - return loadtool_memdump(bi->base_addr + offset, dumplen, argv[2], - format); -} - -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->cfi->total_size); - printf("Sectors in bank %d: %u (%u regions)\n", bank, - bi->cfi->total_sectors, bi->cfi->nregions); - printf("Command set style: %04X\n", bi->cfi->cmdset_style); - flash_id_check(bank, 1); - if (selected_flash_device->nbanks == 2 && !bank) - printf("\nFlash device has 2 banks; flash2 command available\n"); - return(0); -} - -flashcmd_quickprog(argc, argv, bank) - char **argv; -{ - char *targv[4], targ_base[10]; - int stat; - - if (flash_get_cfi(bank) < 0) - return(-1); - if (flash_bank_info[bank].cfi->cmdset_style != 2) { - fprintf(stderr, -"error: this command is currently only implemented for AMD-style flash\n"); - return(-1); - } - if (argc != 4) { - fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n", - argv[0], argv[1]); - return(-1); - } - sprintf(targ_base, "%lx", (u_long) flash_bank_info[bank].base_addr); - targv[0] = "AMFB"; - targv[1] = targ_base; - targv[2] = 0; - tpinterf_make_cmd(targv); - if (tpinterf_send_cmd() < 0) - return(-1); - stat = tpinterf_pass_output(1); - if (stat) - return(stat); - targv[0] = "AMFW"; - targv[1] = argv[2]; - targv[2] = argv[3]; - targv[3] = 0; - if (tpinterf_make_cmd(targv) < 0) { - fprintf(stderr, "error: unable to form AMFW target command\n"); - return(-1); - } - if (tpinterf_send_cmd() < 0) - return(-1); - return tpinterf_pass_output(1); -} - -extern int flashcmd_erase(); -extern int flashcmd_progbin(); -extern int flashcmd_program_m0(); -extern int flashcmd_program_srec(); -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); -}