size_t data_length() const noexcept { if (is_ext2()) return __builtin_bswap64(*(uint64_t*) vla) & 0xffffffff; if (is_ext()) return __builtin_bswap16(*(uint16_t*) vla); return payload(); }
static void makestatefilename(char *filename,int type) { int i; char *exts[] = { ".nes", ".nes.gz", ".unf", ".unf.gz", ".unif",".unif.gz", ".fds", ".fds.gz", ".nsf", ".nsf.gz", 0,0 }; char *types[] = { ".state", ".diskstate", ".sramstate", ".laststate", 0 }; strcpy(filename,config.path_state); log_message("rom->filename = '%s'\n",rom->filename); strcat(filename,rom->filename); for(i=0;exts[i];i++) { if(is_ext(filename,exts[i])) { strcpy(filename + strlen(filename) - strlen(exts[i]),types[type]); i = -1; break; } } if(i != -1) strcat(filename,types[type]); }
void set_payload(const size_t len) { uint16_t pbits = len; if (len > 65535) pbits = 127; else if (len > 125) pbits = 126; bits &= 0x80ff; bits |= (pbits & 0x7f) << 8; if (is_ext()) *(uint16_t*) vla = __builtin_bswap16(len); else if (is_ext2()) *(uint64_t*) vla = __builtin_bswap64(len); assert(data_length() == len); }
/* * While in search mode, enter will switch to current highlighted file's dir. * It checks if file is inside an archive; if so, it removes last part * of file's path while we're inside an archive. * Then returns the index where the real filename begins (to extract the directory path). */ int search_enter_press(const char *str) { char arch_str[PATH_MAX + 1] = {0}; const char *tmp; int len; if (sv.search_archive) { strncpy(arch_str, str, PATH_MAX); while ((len = strlen(arch_str))) { tmp = strrchr(arch_str, '/'); if (is_ext(tmp, arch_ext, NUM(arch_ext))) { break; } arch_str[len - strlen(tmp)] = '\0'; } } if (strlen(arch_str)) { tmp = arch_str; } else { tmp = str; } return (strlen(tmp) - strlen(strrchr(tmp, '/'))); }
static int recursive_search(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { char *fixed_str; int len, r = 0, ret = FTW_CONTINUE; /* * if searching "pippo" from "/home/pippo", * avoid saving "/home/pippo" as a result. */ if (ftwbuf->level == 0) { return ret; } fixed_str = strrchr(path, '/') + 1; /* * if lazy: avoid checking hidden files and * inside hidden folders */ if (sv.search_lazy && fixed_str[0] == '.') { return FTW_SKIP_SUBTREE; } if ((sv.search_archive) && (is_ext(fixed_str, arch_ext, NUM(arch_ext)))) { return search_inside_archive(path); } len = strlen(sv.searched_string); if (!sv.search_lazy) { r = !strncmp(fixed_str, sv.searched_string, len); } else if (strcasestr(fixed_str, sv.searched_string)) { r = 1; } if (r) { strncpy(sv.found_searched[sv.found_cont], path, PATH_MAX); sv.found_cont++; if (sv.found_cont == MAX_NUMBER_OF_FOUND) { ret = FTW_STOP; } } return quit ? FTW_STOP : ret; }
size_t data_offset() const noexcept { size_t len = mask_length(); if (is_ext2()) return len + 8; if (is_ext()) return len + 2; return len; }
int main(int argc, char **argv) { unsigned int start; int bytes_count = 0; char filename[256]; memset(filename, 0, sizeof(filename)); // Parsing command line char c; action_t action = NONE; bool start_addr_specified = false, pgm_specified = false, part_specified = false, bytes_count_specified = false; memtype_t memtype = FLASH; int i; programmer_t *pgm = NULL; const stm8_device_t *part = NULL; while((c = getopt (argc, argv, "r:w:v:nc:p:s:b:luV")) != (char)-1) { switch(c) { case 'c': pgm_specified = true; for(i = 0; pgms[i].name; i++) { if(!strcmp(optarg, pgms[i].name)) pgm = &pgms[i]; } break; case 'p': part_specified = true; part = get_part(optarg); break; case 'l': for(i = 0; stm8_devices[i].name; i++) printf("%s ", stm8_devices[i].name); printf("\n"); exit(0); case 'r': action = READ; strcpy(filename, optarg); break; case 'w': action = WRITE; strcpy(filename, optarg); break; case 'v': action = VERIFY; strcpy(filename, optarg); break; case 'u': action = UNLOCK; start = 0x4800; memtype = OPT; strcpy(filename, "Workaround"); break; case 's': // Start addr is depending on MCU type if(strcasecmp(optarg, "flash") == 0) { memtype = FLASH; } else if(strcasecmp(optarg, "eeprom") == 0) { memtype = EEPROM; } else if(strcasecmp(optarg, "ram") == 0) { memtype = RAM; } else if(strcasecmp(optarg, "opt") == 0) { memtype = OPT; } else { // Start addr is specified explicitely memtype = UNKNOWN; int success = sscanf(optarg, "%x", &start); assert(success); start_addr_specified = true; } break; case 'b': bytes_count = atoi(optarg); bytes_count_specified = true; break; case 'V': print_version_and_exit( (bool)0); break; case '?': print_help_and_exit(argv[0], false); default: print_help_and_exit(argv[0], true); } } if(argc <= 1) print_help_and_exit(argv[0], true); if(pgm_specified && !pgm) { fprintf(stderr, "No valid programmer specified. Possible values are:\n"); dump_pgms( (programmer_t *) &pgms); exit(-1); } if(!pgm) spawn_error("No programmer has been specified"); if(part_specified && !part) { fprintf(stderr, "No valid part specified. Use -l to see the list of supported devices.\n"); exit(-1); } if(!part) spawn_error("No part has been specified"); // Try define memory type by address if(memtype == UNKNOWN) { if((start >= 0x4800) && (start < 0x4880)) { memtype = OPT; } if((start >= part->ram_start) && (start < part->ram_start + part->ram_size)) { memtype = RAM; } else if((start >= part->flash_start) && (start < part->flash_start + part->flash_size)) { memtype = FLASH; } else if((start >= part->eeprom_start) && (start < part->eeprom_start + part->eeprom_size)) { memtype = EEPROM; } } if(memtype != UNKNOWN) { // Selecting start addr depending on // specified part and memtype switch(memtype) { case RAM: if(!start_addr_specified) { start = part->ram_start; } if(!bytes_count_specified || bytes_count > part->ram_size) { bytes_count = part->ram_size; } fprintf(stderr, "Determine RAM area\r\n"); break; case EEPROM: if(!start_addr_specified) { start = part->eeprom_start; } if(!bytes_count_specified || bytes_count > part->eeprom_size) { bytes_count = part->eeprom_size; } fprintf(stderr, "Determine EEPROM area\r\n"); break; case FLASH: if(!start_addr_specified) { start = part->flash_start; } if(!bytes_count_specified || bytes_count > part->flash_size) { bytes_count = part->flash_size; } fprintf(stderr, "Determine FLASH area\r\n"); break; case OPT: if(!start_addr_specified) { start = 0x4800; } size_t opt_size = (part->flash_size <= 8*1024 ? 0x40 : 0x80); if(!bytes_count_specified || bytes_count > opt_size) { bytes_count = opt_size; } fprintf(stderr, "Determine OPT area\r\n"); break; } start_addr_specified = true; } if(!action) spawn_error("No action has been specified"); if(!start_addr_specified) spawn_error("No memtype or start_addr has been specified"); if (!strlen(filename)) spawn_error("No filename has been specified"); if(!action || !start_addr_specified || !strlen(filename)) print_help_and_exit(argv[0], true); if(!usb_init(pgm, pgm->usb_vid, pgm->usb_pid)) spawn_error("Couldn't initialize stlink"); if(!pgm->open(pgm)) spawn_error("Error communicating with MCU. Please check your SWIM connection."); FILE *f; if(action == READ) { fprintf(stderr, "Reading %d bytes at 0x%x... ", bytes_count, start); fflush(stderr); int bytes_count_align = ((bytes_count-1)/256+1)*256; // Reading should be done in blocks of 256 bytes unsigned char *buf = malloc(bytes_count_align); if(!buf) spawn_error("malloc failed"); int recv = pgm->read_range(pgm, part, buf, start, bytes_count_align); if(recv < bytes_count_align) { fprintf(stderr, "\r\nRequested %d bytes but received only %d.\r\n", bytes_count_align, recv); spawn_error("Failed to read MCU"); } if(!(f = fopen(filename, "w"))) spawn_error("Failed to open file"); if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) { fprintf(stderr, "Reading from Intel hex file "); ihex_write(f, buf, start, start+bytes_count); } else if(is_ext(filename, ".s19") || is_ext(filename, ".s8") || is_ext(filename, ".srec")) { printf("Reading from Motorola S-record files are not implemented (yet)\n"); printf("Exiting...\n"); exit(-1); //TODO Remove the above message and exit, and implement reading from S-record. fprintf(stderr, "Reading from Motorola S-record file "); srec_write(f, buf, start, start+bytes_count); } else { fwrite(buf, 1, bytes_count, f); } fclose(f); fprintf(stderr, "OK\n"); fprintf(stderr, "Bytes received: %d\n", bytes_count); } else if (action == VERIFY) { fprintf(stderr, "Verifing %d bytes at 0x%x... ", bytes_count, start); fflush(stderr); int bytes_count_align = ((bytes_count-1)/256+1)*256; // Reading should be done in blocks of 256 bytes unsigned char *buf = malloc(bytes_count_align); if(!buf) spawn_error("malloc failed"); int recv = pgm->read_range(pgm, part, buf, start, bytes_count_align); if(recv < bytes_count_align) { fprintf(stderr, "\r\nRequested %d bytes but received only %d.\r\n", bytes_count_align, recv); spawn_error("Failed to read MCU"); } if(!(f = fopen(filename, "r"))) spawn_error("Failed to open file"); unsigned char *buf2 = malloc(bytes_count); if(!buf2) spawn_error("malloc failed"); int bytes_to_verify; /* reading bytes to RAM */ if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) { bytes_to_verify = ihex_read(f, buf, start, start + bytes_count); } else { fseek(f, 0L, SEEK_END); bytes_to_verify = ftell(f); if(bytes_count_specified) { bytes_to_verify = bytes_count; } else if(bytes_count < bytes_to_verify) { bytes_to_verify = bytes_count; } fseek(f, 0, SEEK_SET); fread(buf2, 1, bytes_to_verify, f); } fclose(f); if(memcmp(buf, buf2, bytes_to_verify) == 0) { fprintf(stderr, "OK\n"); fprintf(stderr, "Bytes verified: %d\n", bytes_to_verify); } else { fprintf(stderr, "FAILED\n"); exit(-1); } } else if (action == WRITE) { if(!(f = fopen(filename, "r"))) spawn_error("Failed to open file"); int bytes_count_align = ((bytes_count-1)/part->flash_block_size+1)*part->flash_block_size; unsigned char *buf = malloc(bytes_count_align); if(!buf) spawn_error("malloc failed"); memset(buf, 0, bytes_count_align); // Clean aligned buffer int bytes_to_write; /* reading bytes to RAM */ if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) { fprintf(stderr, "Writing Intel hex file "); bytes_to_write = ihex_read(f, buf, start, start + bytes_count); } else if (is_ext(filename, ".s19") || is_ext(filename, ".s8") || is_ext(filename, ".srec")) { fprintf(stderr, "Writing Motorola S-record file "); bytes_to_write = srec_read(f, buf, start, start + bytes_count); } else { fprintf(stderr, "Writing binary file "); fseek(f, 0L, SEEK_END); bytes_to_write = ftell(f); if(bytes_count_specified) { bytes_to_write = bytes_count; } else if(bytes_count < bytes_to_write) { bytes_to_write = bytes_count; } fseek(f, 0, SEEK_SET); fread(buf, 1, bytes_to_write, f); } fprintf(stderr, "%d bytes at 0x%x... ", bytes_to_write, start); /* flashing MCU */ int sent = pgm->write_range(pgm, part, buf, start, bytes_to_write, memtype); if(pgm->reset) { // Restarting core (if applicable) pgm->reset(pgm); } fprintf(stderr, "OK\n"); fprintf(stderr, "Bytes written: %d\n", sent); fclose(f); } else if (action == UNLOCK) { int bytes_to_write=part->option_bytes_size; if (part->read_out_protection_mode==ROP_UNKNOWN) spawn_error("No unlocking mode defined for this device. You may need to edit the file stm8.c"); unsigned char *buf=malloc(bytes_to_write); if(!buf) spawn_error("malloc failed"); if (part->read_out_protection_mode==ROP_STM8S_STD) { for (int i=0; i<bytes_to_write;i++) { buf[i]=0; if ((i>0)&&((i&1)==0)) buf[i]=0xff; } } /* flashing MCU */ int sent = pgm->write_range(pgm, part, buf, start, bytes_to_write, memtype); if(pgm->reset) { // Restarting core (if applicable) pgm->reset(pgm); } fprintf(stderr, "Unlocked device. Option bytes reset to default state.\n"); fprintf(stderr, "Bytes written: %d\n", sent); } return(0); }