FreeCalypso > hg > freecalypso-sw
view loadtools/ltflash.c @ 404:7daea2476062
loadagent: Intel flash support added, compiles
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 16 Jun 2014 01:15:17 +0000 |
parents | 7ceeec049be4 |
children |
line wrap: on
line source
/* * This module contains the "core" of fc-loadtool flash operations; * fl*.c modules contain the rest. */ #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 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); }