static void do_test_libeprom24x(void) { int value; do { print_menu(); printf("Enter choice : "); scanf("%d",&value); switch(value) { case 1: get_prod_info(); break; case 2: get_last_error(); break; case 3: initialize(); break; case 4: finalize(); break; case 5: read_u8(); break; case 6: read_u16(); break; case 7: read_u32(); break; case 8: read_to_buffer(); break; case 9: write_u8(); break; case 10: write_u16(); break; case 11: write_u32(); break; case 12: write_from_buffer(); break; case 13: erase_chip(); break; case 100: /* Exit */ break; default: printf("Illegal choice!\n"); } } while (value != 100); return; }
/* * Erase an address range on the nor chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) { struct spi_nor *nor = mtd_to_spi_nor(mtd); u32 addr, len; uint32_t rem; int ret; dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, (long long)instr->len); div_u64_rem(instr->len, mtd->erasesize, &rem); if (rem) return -EINVAL; addr = instr->addr; len = instr->len; ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_ERASE); if (ret) return ret; /* whole-chip erase? */ if (len == mtd->size) { if (erase_chip(nor)) { ret = -EIO; goto erase_err; } /* REVISIT in some cases we could speed up erasing large regions * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up * to use "small sector erase", but that's not always optimal. */ /* "sector"-at-a-time erase */ } else { while (len) { if (nor->erase(nor, addr)) { ret = -EIO; goto erase_err; } addr += mtd->erasesize; len -= mtd->erasesize; } } spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); return ret; erase_err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); instr->state = MTD_ERASE_FAILED; return ret; }
/* * Erase an address range on the flash chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) { struct m25p *flash = mtd_to_m25p(mtd); u32 addr,len; DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", flash->spi->dev.bus_id, __func__, "at", (u32)instr->addr, instr->len); /* sanity checks */ if (instr->addr + instr->len > flash->mtd.size) return -EINVAL; if ((instr->addr % mtd->erasesize) != 0 || (instr->len % mtd->erasesize) != 0) { return -EINVAL; } addr = instr->addr; len = instr->len; mutex_lock(&flash->lock); /* whole-chip erase? */ if (len == flash->mtd.size && erase_chip(flash)) { instr->state = MTD_ERASE_FAILED; mutex_unlock(&flash->lock); return -EIO; /* REVISIT in some cases we could speed up erasing large regions * by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up * to use "small sector erase", but that's not always optimal. */ /* "sector"-at-a-time erase */ } else { while (len) { if (erase_sector(flash, addr)) { instr->state = MTD_ERASE_FAILED; mutex_unlock(&flash->lock); return -EIO; } addr += mtd->erasesize; len -= mtd->erasesize; } } mutex_unlock(&flash->lock); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); return 0; }
static void enable_parallel_programming(void) // TODO { #if 1 PGMW1 &= ~(PAGEL | XA1 | XA0 | BS1); read_switch(); // Applied +5V & +12V erase_chip(); write_fuse(0, 0x99E0); #else _delay_us(100); PGMW2 &= ~RESETb; xtal1_pulse(); xtal1_pulse(); xtal1_pulse(); PGMW1 &= ~(PAGEL | XA1 | XA0 | BS1); _delay_us(1); read_switch(); apply_high_voltage_to_reset(); _delay_us(1); #endif }
int main(int argc, char *argv[]) { char *mode; if (argc == 1) { printf("Syntax: epsiflash erase|read|burn [filename]\n"); exit (1);} hardware_init(); filename = argv[2]; mode = argv[1]; probe_chip(); printf("Chip: %s - %dKB, %s\n", chips[chipindex].name, chips[chipindex].size / 1024, chips[chipindex].adapter); if (strcmp(chips[chipindex].name,"UNKNOWN")==0) { fprintf(stderr,"Chip is unsupported or not inserted properly\n"); exit(-1); } if (strcmp(mode,"burn")==0) { program_chip(); printf("\n"); exit(1); } if (strcmp(mode,"read")==0) { read_chip(); printf("\n"); exit(1); } if (strcmp(mode, "erase")==0) { erase_chip(); printf("\n"); exit(1); } return 0; }
int main(int argc, char *argv[]) { const char *pname = argv[0]; uint32_t address = 0, read_size = 0, write_size = 0; uint32_t erase_start = 0, erase_size = 0; bool erase = false, do_clear = false; bool program = false, erase_all = false, info = false, do_read = false; bool enable_4B = false, disable_4B = false; bool show_help = false, show_version = false; bool no_action = false, tune = false; char *write_file = NULL, *read_file = NULL, *part_name = NULL; bool ffs_toc_seen = false; int rc; while(1) { static struct option long_opts[] = { {"address", required_argument, NULL, 'a'}, {"size", required_argument, NULL, 's'}, {"partition", required_argument, NULL, 'P'}, {"bmc", no_argument, NULL, 'b'}, {"enable-4B", no_argument, NULL, '4'}, {"disable-4B", no_argument, NULL, '3'}, {"read", required_argument, NULL, 'r'}, {"erase-all", no_argument, NULL, 'E'}, {"erase", no_argument, NULL, 'e'}, {"program", required_argument, NULL, 'p'}, {"force", no_argument, NULL, 'f'}, {"info", no_argument, NULL, 'i'}, {"tune", no_argument, NULL, 't'}, {"dummy", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {"debug", no_argument, NULL, 'g'}, {"side", required_argument, NULL, 'S'}, {"toc", required_argument, NULL, 'T'}, {"clear", no_argument, NULL, 'c'} }; int c, oidx = 0; c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihvbtgS:T:c", long_opts, &oidx); if (c == EOF) break; switch(c) { case 'a': address = strtoul(optarg, NULL, 0); break; case 's': read_size = write_size = strtoul(optarg, NULL, 0); break; case 'P': part_name = strdup(optarg); break; case '4': enable_4B = true; break; case '3': disable_4B = true; break; case 'r': do_read = true; read_file = strdup(optarg); break; case 'E': erase_all = erase = true; break; case 'e': erase = true; break; case 'p': program = true; write_file = strdup(optarg); break; case 'f': must_confirm = false; break; case 'd': must_confirm = false; dummy_run = true; break; case 'i': info = true; break; case 'b': bmc_flash = true; break; case 't': tune = true; break; case 'v': show_version = true; break; case 'h': show_help = show_version = true; break; case 'g': libflash_debug = true; break; case 'S': flash_side = atoi(optarg); break; case 'T': ffs_toc_seen = true; ffs_toc = strtoul(optarg, NULL, 0); break; case 'c': do_clear = true; break; default: exit(1); } } /* Check if we need to access the flash at all (which will * also tune them as a side effect */ no_action = !erase && !program && !info && !do_read && !enable_4B && !disable_4B && !tune && !do_clear; /* Nothing to do, if we didn't already, print usage */ if (no_action && !show_version) show_help = show_version = true; if (show_version) print_version(); if (show_help) print_help(pname); if (no_action) return 0; /* --enable-4B and --disable-4B are mutually exclusive */ if (enable_4B && disable_4B) { fprintf(stderr, "--enable-4B and --disable-4B are mutually" " exclusive !\n"); exit(1); } /* 4B not supported on BMC flash */ if (enable_4B && bmc_flash) { fprintf(stderr, "--enable-4B not supported on BMC flash !\n"); exit(1); } /* partitions not supported on BMC flash */ if (part_name && bmc_flash) { fprintf(stderr, "--partition not supported on BMC flash !\n"); exit(1); } /* part-name and erase-all make no sense together */ if (part_name && erase_all) { fprintf(stderr, "--partition and --erase-all are mutually" " exclusive !\n"); exit(1); } /* Read command should always come with a file */ if (do_read && !read_file) { fprintf(stderr, "Read with no file specified !\n"); exit(1); } /* Program command should always come with a file */ if (program && !write_file) { fprintf(stderr, "Program with no file specified !\n"); exit(1); } /* If both partition and address specified, error out */ if (address && part_name) { fprintf(stderr, "Specify partition or address, not both !\n"); exit(1); } if (do_clear && !part_name) { fprintf(stderr, "--clear only supported on a partition name\n"); exit(1); } /* Explicitly only support two sides */ if (flash_side != 0 && flash_side != 1) { fprintf(stderr, "Unexpected value for --side '%d'\n", flash_side); exit(1); } if (ffs_toc_seen && flash_side) { fprintf(stderr, "--toc and --side are exclusive"); exit(1); } /* If file specified but not size, get size from file */ if (write_file && !write_size) { struct stat stbuf; if (stat(write_file, &stbuf)) { perror("Failed to get file size"); exit(1); } write_size = stbuf.st_size; } if (bmc_flash) { if (arch_flash_bmc(NULL, 1) == -1) { fprintf(stderr, "Can't switch to BMC flash on this architecture\n"); exit(1); } } if (arch_flash_init(&bl, NULL, true)) exit(1); on_exit(exiting, NULL); rc = blocklevel_get_info(bl, &fl_name, &fl_total_size, &fl_erase_granule); if (rc) { fprintf(stderr, "Error %d getting flash info\n", rc); exit(1); } /* If -t is passed, then print a nice message */ if (tune) printf("Flash and controller tuned\n"); /* If read specified and no read_size, use flash size */ if (do_read && !read_size && !part_name) read_size = fl_total_size; /* We have a partition specified, grab the details */ if (part_name) lookup_partition(part_name); /* We have a partition, adjust read/write size if needed */ if (ffsh && ffs_index >= 0) { uint32_t pstart, pmaxsz, pactsize; bool ecc; int rc; rc = ffs_part_info(ffsh, ffs_index, NULL, &pstart, &pmaxsz, &pactsize, &ecc); if (rc) { fprintf(stderr,"Failed to get partition info\n"); exit(1); } if (!ecc && do_clear) { fprintf(stderr, "The partition on which to do --clear " "does not have ECC, are you sure?\n"); check_confirm(); /* Still confirm later on */ must_confirm = true; } /* Read size is obtained from partition "actual" size */ if (!read_size) read_size = pactsize; /* Write size is max size of partition */ if (!write_size) write_size = pmaxsz; /* Crop write size to partition size */ if (write_size > pmaxsz) { printf("WARNING: Size (%d bytes) larger than partition" " (%d bytes), cropping to fit\n", write_size, pmaxsz); write_size = pmaxsz; } /* If erasing, check partition alignment */ if (erase && ((pstart | pmaxsz) & 0xfff)) { fprintf(stderr,"Partition not aligned properly\n"); exit(1); } /* Set address */ address = pstart; } /* Align erase boundaries */ if (erase && !erase_all) { uint32_t mask = 0xfff; uint32_t erase_end; /* Dummy size for erase, will be adjusted later */ if (!write_size) write_size = 1; erase_start = address & ~mask; erase_end = ((address + write_size) + mask) & ~mask; erase_size = erase_end - erase_start; if (erase_start != address || erase_size != write_size) fprintf(stderr, "WARNING: Erase region adjusted" " to 0x%08x..0x%08x\n", erase_start, erase_end); } /* Process commands */ if (enable_4B) enable_4B_addresses(); if (disable_4B) disable_4B_addresses(); if (info) { /* * Don't pass through modfied TOC value if the modification was done * because of --size, but still respect if it came from --toc (we * assume the user knows what they're doing in that case) */ print_flash_info(flash_side ? 0 : ffs_toc); } /* Unlock flash (PNOR only) */ if ((erase || program || do_clear) && !bmc_flash) { need_relock = arch_flash_set_wrprotect(bl, false); if (need_relock == -1) { fprintf(stderr, "Architecture doesn't support write protection on flash\n"); need_relock = 0; exit (1); } } if (do_read) do_read_file(read_file, address, read_size); if (erase_all) erase_chip(); else if (erase) erase_range(erase_start, erase_size, program); if (program) program_file(write_file, address, write_size); if (do_clear) set_ecc(address, write_size); return 0; }
int main(int argc, char *argv[]) { char *file_name = NULL; unsigned char options = 0x00; signal(SIGINT, sigint_handler); if (argc < 2) usage(); for (int i = 1; i < argc; i++) { if (argv[i][0] != '-') { if (!file_name) file_name = argv[i]; else usage(); } else { if (options || strlen(argv[i]) > 2) usage(); switch (argv[i][1]) { case 's': options |= OPTIONS_SKIP_VALIDATION; break; case 'l': options |= OPTIONS_LIST_DEVICES; break; case 'e': options |= OPTIONS_ERASE_CHIP; break; case 'h': options |= OPTIONS_HELP; break; case 'v': options |= OPTIONS_VERSION; break; default: usage(); break; } } } if (!file_name && (options & OPTIONS_SKIP_VALIDATION)) usage(); if (file_name && (options & ~OPTIONS_SKIP_VALIDATION)) usage(); switch (options) { case OPTIONS_LIST_DEVICES: list_devices(); break; case OPTIONS_ERASE_CHIP: erase_chip(); break; case OPTIONS_HELP: usage(); break; case OPTIONS_VERSION: printf("saturn-loader "VERSION", " "© 2016 Andrew Milkovich" ", see LICENSE for details\n"); exit(0); break; default: flash(file_name, options & OPTIONS_SKIP_VALIDATION); break; } return 0; }
uint8_t flash(FlashControl* flash_control,bool bmc_flash, uint32_t address, char* write_file, char* obj_path) { bool has_sfc = false, has_ast = false, use_lpc = true; bool erase = true, program = true; int rc; printf("flasher: %s, BMC = %d, address = 0x%x\n",write_file,bmc_flash,address); #ifdef __arm__ /* Check platform */ check_platform(&has_sfc, &has_ast); /* Prepare for access */ if(bmc_flash) { if(!has_ast) { fprintf(stderr, "No BMC on this platform\n"); return FLASH_SETUP_ERROR; } rc = flash_access_setup_bmc(use_lpc, erase || program); if(rc) { return FLASH_SETUP_ERROR; } } else { if(!has_ast && !has_sfc) { fprintf(stderr, "No BMC nor SFC on this platform\n"); return FLASH_SETUP_ERROR; } rc = flash_access_setup_pnor(use_lpc, has_sfc, erase || program); if(rc) { return FLASH_SETUP_ERROR; } } rc = flash_get_info(fl_chip, &fl_name, &fl_total_size, &fl_erase_granule); if(rc) { fprintf(stderr, "Error %d getting flash info\n", rc); return FLASH_SETUP_ERROR; } #endif if(strcmp(write_file,"")!=0) { // If file specified but not size, get size from file struct stat stbuf; if(stat(write_file, &stbuf)) { perror("Failed to get file size"); return FLASH_ERROR; } uint32_t write_size = stbuf.st_size; #ifdef __arm__ rc = erase_chip(); if(rc) { return FLASH_ERROR; } rc = program_file(flash_control, write_file, address, write_size); if(rc) { return FLASH_ERROR; } #endif printf("Flash done\n"); } else { printf("Flash tuned\n"); } return FLASH_OK; }