static int read_all(struct elf32_info *info, FILE *in) { memset(info, 0, sizeof(info)); if (read_ehdr(info, in) < 0) return -1; if (info->file_ehdr.e_machine != EM_MSP430) printc_err("elf32: warning: unknown machine type: 0x%x\n", info->file_ehdr.e_machine); if (read_phdr(info, in) < 0) return -1; if (read_shdr(info, in) < 0) return -1; return 0; }
static int bsl_sync(struct bsl_device *dev) { static const uint8_t c = DATA_HDR; int tries = 2; if (dev->serial->ops->flush(dev->serial) < 0) { pr_error("bsl: tcflush"); return -1; } while (tries--) if (!(dev->serial->ops->send(dev->serial, &c, 1) || bsl_ack(dev))) return 0; printc_err("bsl: sync failed\n"); return -1; }
static int bsl_ctl(device_t dev_base, device_ctl_t type) { (void)dev_base; switch (type) { case DEVICE_CTL_HALT: /* Ignore halt requests */ return 0; case DEVICE_CTL_RESET: /* Ignore reset requests */ return 0; default: printc_err("bsl: CPU control is not possible\n"); } return -1; }
static int verify_checksum(struct bsl_device *dev) { uint8_t cklow = 0xff; uint8_t ckhigh = 0xff; int i; for (i = 0; i < dev->reply_len; i += 2) cklow ^= dev->reply_buf[i]; for (i = 1; i < dev->reply_len; i += 2) ckhigh ^= dev->reply_buf[i]; if (cklow || ckhigh) { printc_err("bsl: checksum invalid (%02x %02x)\n", cklow, ckhigh); return -1; } return 0; }
static int timer_config(struct simio_device *dev, const char *param, char **arg_text) { struct timer *tr = (struct timer *)dev; if (!strcasecmp(param, "base")) return config_addr(&tr->base_addr, arg_text); if (!strcasecmp(param, "iv")) return config_addr(&tr->iv_addr, arg_text); if (!strcasecmp(param, "irq0")) return config_irq(&tr->irq0, arg_text); if (!strcasecmp(param, "irq1")) return config_irq(&tr->irq1, arg_text); if (!strcasecmp(param, "set")) return config_channel(tr, arg_text); printc_err("timer: config: unknown parameter: %s\n", param); return -1; }
static int cmd_sym_find(char **arg) { regex_t find_preg; char *expr = get_arg(arg); if (!expr) { stab_enum(print_sym, NULL); return 0; } if (regcomp(&find_preg, expr, REG_EXTENDED | REG_NOSUB)) { printc_err("sym: failed to compile: %s\n", expr); return -1; } stab_enum(find_sym, &find_preg); regfree(&find_preg); return 0; }
/* Write a word to RAM. */ static int write_ram_word(sport_t fd, address_t addr, uint16_t value) { uint8_t req[6]; struct packet pkt; req[0] = addr; req[1] = addr >> 8; req[2] = 0; req[3] = 0; req[4] = value; req[5] = value >> 8; if (xfer(fd, APP_JTAG430, GLOBAL_POKE, sizeof(req), req, &pkt) < 0) { printc_err("goodfet: failed to write word at 0x%x\n", addr); return -1; } return 0; }
int cmd_step(char **arg) { char *count_text = get_arg(arg); address_t count = 1; int i; if (count_text) { if (expr_eval(count_text, &count) < 0) { printc_err("step: can't parse count: %s\n", count_text); return -1; } } for (i = 0; i < count; i++) if (device_ctl(DEVICE_CTL_STEP) < 0) return -1; reader_set_repeat("step"); return cmd_regs(NULL); }
transport_t olimex_open(const char *devpath) { struct olimex_transport *tr = malloc(sizeof(*tr)); struct usb_device *dev; char buf[64]; if (!tr) { pr_error(__FILE__": can't allocate memory"); return NULL; } tr->base.destroy = usbtr_destroy; tr->base.send = usbtr_send; tr->base.recv = usbtr_recv; usb_init(); usb_find_busses(); usb_find_devices(); if (devpath) dev = usbutil_find_by_loc(devpath); else dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT); if (!dev) { free(tr); return NULL; } if (open_device(tr, dev) < 0) { printc_err(__FILE__ ": failed to open Olimex device\n"); return NULL; } /* Flush out lingering data */ while (usb_bulk_read(tr->handle, USB_FET_IN_EP, buf, sizeof(buf), 100) >= 0); return (transport_t)tr; }
static int goodfet_ctl(device_t dev_base, device_ctl_t type) { struct goodfet *gc = (struct goodfet *)dev_base; switch (type) { case DEVICE_CTL_RESET: return goodfet_reset(gc); case DEVICE_CTL_RUN: return goodfet_run(gc); case DEVICE_CTL_HALT: return goodfet_halt(gc); default: printc_err("goodfet: unsupported operation\n"); return -1; } return 0; }
static int init_device(sport_t fd) { struct packet pkt; printc_dbg("Initializing...\n"); if (xfer(fd, APP_JTAG430, GLOBAL_NOK, 0, NULL, &pkt) < 0) { printc_err("goodfet: comms test failed\n"); return -1; } printc_dbg("Setting up JTAG pins\n"); if (xfer(fd, APP_JTAG430, GLOBAL_SETUP, 0, NULL, &pkt) < 0) { printc_err("goodfet: SETUP command failed\n"); return -1; } printc_dbg("Starting JTAG\n"); if (xfer(fd, APP_JTAG430, GLOBAL_START, 0, NULL, &pkt) < 0) { printc_err("goodfet: START command failed\n"); return -1; } if (pkt.len < 1) { printc_err("goodfet: bad response to JTAG START\n"); return -1; } printc("JTAG ID: 0x%02x\n", pkt.data[0]); if (pkt.data[0] != 0x89 && pkt.data[0] != 0x91) { printc_err("goodfet: unexpected JTAG ID: 0x%02x\n", pkt.data[0]); xfer(fd, APP_JTAG430, GLOBAL_STOP, 0, NULL, &pkt); return -1; } printc_dbg("Halting CPU\n"); if (xfer(fd, APP_JTAG430, JTAG430_HALTCPU, 0, NULL, &pkt) < 0) { printc_err("goodfet: HALTCPU command failed\n"); xfer(fd, APP_JTAG430, GLOBAL_STOP, 0, NULL, &pkt); return -1; } return 0; }
static int syms_load_syms(struct elf32_info *info, FILE *in, Elf32_Shdr *s) { int len = s->sh_size / 16; int i; if (fseek(in, s->sh_offset, SEEK_SET) < 0) { pr_error("elf32: can't seek to symbols"); return -1; } for (i = 0; i < len; i++) { Elf32_Sym y; int st; const char *name; if (parse_sym(&y, in) < 0) { pr_error("elf32: error reading symbols"); return -1; } st = ELF32_ST_TYPE(y.st_info); name = info->string_tab + y.st_name; if (y.st_name > info->string_len) { printc_err("elf32: symbol out of bounds\n"); return -1; } if (name[0] && (st == STT_OBJECT || st == STT_FUNC || st == STT_SECTION || st == STT_COMMON || st == STT_TLS) && stab_set(info->string_tab + y.st_name, y.st_value) < 0) return -1; } return 0; }
/* Write a word-aligned flash block. The starting address must be within * the flash memory range. */ static int write_flash_block(sport_t fd, address_t addr, address_t len, const uint8_t *data) { uint8_t req[MAX_MEM_BLOCK + 4]; struct packet pkt; req[0] = addr >> 0; req[1] = addr >> 8; req[2] = addr >> 16; req[3] = addr >> 24; memcpy(req + 4, data, len); if (xfer(fd, APP_JTAG430, JTAG430_WRITEFLASH, len + 4, req, &pkt) < 0) { printc_err("goodfet: failed to write " "flash block of size %d at 0x%x\n", len, addr); return -1; } return 0; }
static int do_command(char *arg, int interactive) { const char *cmd_text; int len = strlen(arg); while (len && isspace(arg[len - 1])) len--; arg[len] = 0; cmd_text = get_arg(&arg); if (cmd_text) { char translated[1024]; struct cmddb_record cmd; if (translate_alias(cmd_text, arg, translated, sizeof(translated)) < 0) return -1; arg = translated; cmd_text = get_arg(&arg); if (!cmddb_get(cmd_text, &cmd)) { int old = in_reader_loop; int ret; in_reader_loop = interactive; ret = cmd.func(&arg); in_reader_loop = old; return ret; } printc_err("unknown command: %s (try \"help\")\n", cmd_text); return -1; } return 0; }
int coff_extract(FILE *in, binfile_imgcb_t cb, void *user_data) { struct coff_header hdr; uint8_t *shdrs; int ret = 0; int i; if (read_header(in, &hdr) < 0) return -1; if (read_sechdrs(in, &hdr, &shdrs) < 0) return -1; for (i = 0; i < hdr.sec_count; i++) { uint8_t *header = shdrs + SHDR_SIZE * i; uint32_t flags = LE_LONG(header, 40); if (((flags & STYP_TEXT) || (flags & STYP_DATA)) && !(flags & STYP_NOLOAD)) { uint32_t addr = LE_LONG(header, 8); uint32_t offset = LE_LONG(header, 20); uint32_t size = LE_LONG(header, 16); if (load_section(in, addr, offset, size, cb, user_data) < 0) { printc_err("coff: error while loading " "section %d\n", i); ret = -1; break; } } } if (shdrs) free(shdrs); return ret; }
static int reset_sequence(sport_t fd) { static const int states[] = { SPORT_MC_RTS, SPORT_MC_RTS | SPORT_MC_DTR, SPORT_MC_DTR }; int i; printc_dbg("Resetting GoodFET...\n"); for (i = 0; i < 3; i++) { if (sport_set_modem(fd, states[i]) < 0) { printc_err("goodfet: failed at step %d: %s\n", i, last_error()); return -1; } delay_ms(20); } return 0; }
static int send_command(struct bsl_device *dev, int code, uint16_t addr, const uint8_t *data, int len) { uint8_t pktbuf[256]; uint8_t cklow = 0xff; uint8_t ckhigh = 0xff; int pktlen = data ? len + 4 : 4; int i; if (pktlen + 6 > sizeof(pktbuf)) { printc_err("bsl: payload too large: %d\n", len); return -1; } pktbuf[0] = DATA_HDR; pktbuf[1] = code; pktbuf[2] = pktlen; pktbuf[3] = pktlen; pktbuf[4] = addr & 0xff; pktbuf[5] = addr >> 8; pktbuf[6] = len & 0xff; pktbuf[7] = len >> 8; if (data) memcpy(pktbuf + 8, data, len); for (i = 0; i < pktlen + 4; i += 2) cklow ^= pktbuf[i]; for (i = 1; i < pktlen + 4; i += 2) ckhigh ^= pktbuf[i]; pktbuf[pktlen + 4] = cklow; pktbuf[pktlen + 5] = ckhigh; return dev->serial->ops->send(dev->serial, pktbuf, pktlen + 6); }
transport_t bslhid_open(const char *dev_path, const char *requested_serial) { struct bslhid_transport *tr = malloc(sizeof(*tr)); struct usb_device *dev; if (!tr) { pr_error("bslhid: can't allocate memory"); return NULL; } memset(tr, 0, sizeof(*tr)); tr->base.ops = &bslhid_transport_class; usb_init(); usb_find_busses(); usb_find_devices(); if (dev_path) dev = usbutil_find_by_loc(dev_path); else dev = usbutil_find_by_id(BSLHID_VID, BSLHID_PID, requested_serial); if (!dev) { free(tr); return NULL; } if (open_device(tr, dev) < 0) { printc_err("bslhid: failed to open BSL HID device\n"); free(tr); return NULL; } bslhid_flush(&tr->base); return &tr->base; }
transport_t cp210x_open(const char *devpath, const char *requested_serial, int baud_rate, uint16_t product, uint16_t vendor) { struct cp210x_transport *tr = malloc(sizeof(*tr)); struct usb_device *dev; if (!tr) { pr_error(__FILE__": can't allocate memory"); return NULL; } tr->base.ops = &cp210x_class; usb_init(); usb_find_busses(); usb_find_devices(); if (devpath) dev = usbutil_find_by_loc(devpath); else dev = usbutil_find_by_id(product, vendor, requested_serial); if (!dev) { free(tr); return NULL; } if (open_device(tr, dev, baud_rate) < 0) { printc_err(__FILE__ ": failed to open CP210X device\n"); free(tr); return NULL; } usbtr_flush(&tr->base); return (transport_t)tr; }
/* Write a word-aligned block to any kind of memory. * returns the number of bytes written or -1 on failure */ static int write_words(device_t dev, const struct chipinfo_memory *m, address_t addr, address_t len, const uint8_t *data) { struct goodfet *gc = (struct goodfet *)dev; sport_t fd = gc->serial_fd; int r; if (len > MAX_MEM_BLOCK) len = MAX_MEM_BLOCK; if (m->type != CHIPINFO_MEMTYPE_FLASH) { len = 2; r = write_ram_word(fd, addr, r16le(data)); } else { r = write_flash_block(fd, addr, len, data); } if (r < 0) { printc_err("goodfet: write_words at address 0x%x failed\n", addr); return -1; } return len; }
static int goodfet_reset(struct goodfet *gc) { static const uint8_t cmd_seq[] = { JTAG430_RELEASECPU, GLOBAL_STOP, GLOBAL_START, JTAG430_HALTCPU }; int i; /* We don't have a POR request, so just restart JTAG */ for (i = 0; i < 4; i++) { struct packet pkt; if (xfer(gc->serial_fd, APP_JTAG430, cmd_seq[i], 0, NULL, &pkt) < 0) { printc_err("goodfet: reset: command 0x%02x failed\n", cmd_seq[i]); return -1; } } return 0; }
static int read_ehdr(struct elf32_info *info, FILE *in) { /* Read and check the ELF header */ char *id; rewind(in); if (elf_version(EV_CURRENT) == EV_NONE) { printc_err("elf32: elf_version failed"); return -1; } /* ELF_C_READ_MMAP* is not available in Mac OS X macports libelf @0.8.10_1 */ info->elf = elf_begin(fileno(in), ELF_C_READ, NULL); if (info->elf == 0) { printc_err("elf32: elf_begin failed"); return -1; } if (elf_kind(info->elf) != ELF_K_ELF) { printc_err("elf32: elf_kind is not ELF_K_ELF"); return -1; } if (gelf_getehdr(info->elf, &info->file_ehdr) == 0) { printc_err("elf32: couldn't get ELF header"); return -1; } if ((id = elf_getident(info->elf, NULL)) == 0) { printc_err("elf32: couldn't getident"); return -1; } if (memcmp(id, elf32_id, sizeof(elf32_id))) { printc_err("elf32: not an ELF32 file\n"); return -1; } return 0; }
/* power supply off */ p->data_register &= ~(POWER | RESET); do_bus_pirate_data(p); } static void jtbp_connect(struct jtdev *p) { // unsure what this function does, I presume my setup w/ bus pirate is // "always enabled" } static void jtbp_release(struct jtdev *p) { // unsure what this function does, I presume my setup w/ bus pirate is // "always enabled" } static void jtbp_tck(struct jtdev *p, int out) { if (out) p->data_register |= TCK; else p->data_register &= ~TCK; do_bus_pirate_data(p); } static void jtbp_tms(struct jtdev *p, int out) { if (out) p->data_register |= TMS; else p->data_register &= ~TMS; do_bus_pirate_data(p); } static void jtbp_tdi(struct jtdev *p, int out) { if (out) p->data_register |= TDI; else p->data_register &= ~TDI; do_bus_pirate_data(p); } static void jtbp_rst(struct jtdev *p, int out) { if (out) p->data_register |= RESET; else p->data_register &= ~RESET; do_bus_pirate_data(p); } static void jtbp_tst(struct jtdev *p, int out) { // Test not supported on bus pirate } static int jtbp_tdo_get(struct jtdev *p) { do_bus_pirate_data(p); return (p->data_register & TDO) ? 1 : 0; } static void jtbp_tclk(struct jtdev *p, int out) { jtbp_tdi(p, out); } static int jtbp_tclk_get(struct jtdev *p) { do_bus_pirate_data(p); return (p->data_register & TDI) ? 1 : 0; } static void jtbp_tclk_strobe(struct jtdev *p, unsigned int count) { int i; for (i = 0; i < count; i++) { jtbp_tclk(p, 1); jtbp_tclk(p, 0); if (p->failed) return; } } static void jtbp_led_green(struct jtdev *p, int out) { // TCLK not supported by bus pirate } static void jtbp_led_red(struct jtdev *p, int out) { // TCLK not supported by bus pirate } #else /* __linux__ */ static int jtbp_open(struct jtdev *p, const char *device) { printc_err("jtdev: driver is not supported on this platform\n"); p->failed = 1; return -1; }
static int process_data_line(address_t address, const char *buf, binfile_imgcb_t cb, void *user_data) { uint8_t data[64]; int data_len = 0; int value = 0; int vc = 0; struct binfile_chunk ch = {0}; while (*buf) { int c = *(buf++); int x; if (isspace(c)) { if (vc) { if (data_len >= sizeof(data)) goto too_long; data[data_len++] = value; } vc = 0; } else { if (isdigit(c)) { x = c - '0'; } else if (c >= 'A' && c <= 'F') { x = c - 'A' + 10; } else if (c >= 'a' && c <= 'f') { x = c - 'a' + 10; } else { printc_err("titext: unexpected " "character: %c\n", c); return -1; } if (vc >= 2) { printc_err("titext: too many digits " "in hex value\n"); return -1; } value = (value << 4) | x; vc++; } } if (vc) { if (data_len >= sizeof(data)) goto too_long; data[data_len++] = value; } ch.addr = address; ch.data = data; ch.len = data_len; if (cb(user_data, &ch) < 0) return -1; return data_len; too_long: printc_err("titext: too many data bytes\n"); return -1; }
int expr_eval(const char *text, address_t *addr) { const char *text_save = text; int last_cc = 1; char token_buf[64]; int token_len = 0; struct addr_exp_state s = {0}; s.last_operator = '('; for (;;) { int cc; /* Figure out what class this character is */ if (*text == '+' || *text == '-' || *text == '*' || *text == '/' || *text == '%' || *text == '(' || *text == ')') cc = 1; else if (!*text || isspace(*text)) cc = 2; else if (isalnum(*text) || *text == '.' || *text == '_' || *text == '$' || *text == ':') cc = 3; else { printc_err("illegal character in expression: %c\n", *text); return -1; } /* Accumulate and process token text */ if (cc == 3) { if (token_len + 1 < sizeof(token_buf)) token_buf[token_len++] = *text; } else if (token_len) { token_buf[token_len] = 0; token_len = 0; if (addr_exp_data(&s, token_buf) < 0) goto fail; } /* Process operators */ if (cc == 1) { if (addr_exp_op(&s, *text) < 0) goto fail; } if (!*text) break; last_cc = cc; text++; } if (addr_exp_finish(&s, addr) < 0) goto fail; return 0; fail: printc_err("bad address expression: %s\n", text_save); return -1; }
static int jtbp_open(struct jtdev *p, const char *device) { int i; char in_buff, out_buff; struct termios tio; const char* response = "BBIO1"; p->port = open(device, O_RDWR | O_NOCTTY); if (p->port < 0) { printc_err("jtdev: can't open %s: %s\n", device, last_error()); return -1; } memset(&tio, 0, sizeof(tio)); tio.c_cflag = B115200 | CS8 | CLOCAL | CREAD; tio.c_iflag = IGNPAR; tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cc[VTIME] = 1; tio.c_cc[VMIN] = 0; tcflush(p->port, TCIFLUSH); tcsetattr(p->port, TCSANOW, &tio); // If it's in the middle of spewing something, let it finish while(read(p->port, &in_buff, 1) != 0); out_buff = 0; for(i=0; i<20; ++i) { if(write(p->port, &out_buff, 1) < 1) { pr_error("jtdev: failed writing to serial port"); p->failed = 1; } if(read(p->port, &in_buff, 1) > 0) { break; } } if (i == 20) { printc_err("jtdev: bus pirate failed to enter bit bang mode\n"); return -1; } if(in_buff != *response) { printc_err("jtdev: bus pirate: got bad response %c\n", in_buff); return -1; } ++response; for(i=0; i<4; ++i, ++response) { if(read(p->port, &in_buff, 1) <= 0) { printc_err("jtdev: bus pirate: got no response\n"); } if(in_buff != *response) { printc_err("jtdev: bus pirate: got bad response %c\n", in_buff); return -1; } } out_buff = CMD_CONFIG_PIN_DIR(TDO); if(write(p->port, &out_buff, 1) < 1) { pr_error("jtdev: failed writing to serial port"); p->failed = 1; } if(read(p->port, &in_buff, 1) <= 0) { printc_err("jtdev: bus pirate: got no response\n"); } p->data_register = 0; p->control_register = 0; p->failed = 0; do_bus_pirate_data(p); return 0; }
int cmd_erase(char **arg) { const char *type_text = get_arg(arg); const char *seg_text = get_arg(arg); device_erase_type_t type = DEVICE_ERASE_MAIN; address_t segment = 0; address_t total_size = 0; address_t segment_size = 0; if (seg_text && expr_eval(seg_text, &segment) < 0) { printc_err("erase: invalid expression: %s\n", seg_text); return -1; } if (type_text) { if (!strcasecmp(type_text, "all")) { type = DEVICE_ERASE_ALL; } else if (!strcasecmp(type_text, "segment")) { type = DEVICE_ERASE_SEGMENT; if (!seg_text) { printc_err("erase: expected segment " "address\n"); return -1; } } else if (!strcasecmp(type_text, "segrange")) { const char *total_text = get_arg(arg); const char *ss_text = get_arg(arg); if (!(total_text && ss_text)) { printc_err("erase: you must specify " "total and segment sizes\n"); return -1; } if (expr_eval(total_text, &total_size) < 0) { printc_err("erase: invalid expression: %s\n", total_text); return -1; } if (expr_eval(ss_text, &segment_size) < 0) { printc_err("erase: invalid expression: %s\n", ss_text); return -1; } if (segment_size > 0x200 || segment_size < 0x40) { printc_err("erase: invalid segment size: " "0x%x\n", segment_size); return -1; } } else { printc_err("erase: unknown erase type: %s\n", type_text); return -1; } } if (device_ctl(DEVICE_CTL_HALT) < 0) return -1; if (!segment_size) { printc("Erasing...\n"); return device_erase(type, segment); } else { printc("Erasing segments...\n"); while (total_size >= segment_size) { printc_dbg("Erasing 0x%04x...\n", segment); if (device_erase(DEVICE_ERASE_SEGMENT, segment) < 0) return -1; total_size -= segment_size; segment += segment_size; } } return 0; }
static int syms_load_syms(struct elf32_info *info, FILE *in, GElf_Shdr *s) { const char sym_debug = 0; int number = 0; int added = 0; char *name; /* now loop through the symbol table and print it*/ #if 1 /* Good: This works. */ Elf32_Sym *esym; Elf32_Sym *lastsym; esym = (Elf32_Sym*) info->string_data->d_buf; lastsym = (Elf32_Sym*) ((char*)info->string_data->d_buf + info->string_data->d_size); for (; esym && (esym < lastsym); esym++) { #else /* BAD: For some reason, st_value = 0 for all symbols? */ GElf_Sym isym; GElf_Sym *esym; while ((esym = gelf_getsym(info->string_data, number, &isym))) { #endif int st; st = ELF32_ST_TYPE(esym->st_info); name = elf_strptr(info->elf, s->sh_link, (size_t)esym->st_name); if (sym_debug) { printc("[%3d] name:%16s st:%d sz:%d info:%d other:%d value:%d ", number, name ? name : "<NULL>", st, esym->st_size, esym->st_info, esym->st_other, esym->st_value); } if ((name != NULL && name[0] != 0) && (st == STT_OBJECT || st == STT_FUNC || st == STT_SECTION || st == STT_COMMON || st == STT_TLS)) { if (sym_debug) { printc("stab_set(%s, %d)\n", name, esym->st_value); } if (stab_set(name, esym->st_value) < 0) { printc_err("elf32: stab_set #%d failed\n", number); return -1; } added++; } else { if (sym_debug) { printc("was ignored\n"); } } if (name == NULL) { printc_err("elf32: null symbol name %s\n", elf_errmsg(elf_errno())); exit(-1); } number++; } printc("load_syms found %d symbols, added %d\n", number, added); return 0; } int elf32_syms(FILE *in) { struct elf32_info info; GElf_Shdr *s; int ret = 0; if (read_all(&info, in) < 0) return -1; s = find_shdr(&info, SHT_SYMTAB); if (!s) { printc_err("elf32: no symbol table\n"); return -1; } if (s->sh_link <= 0 || s->sh_link >= info.file_ehdr.e_shnum) { printc_err("elf32: no string table\n"); return -1; } if (syms_load_strings(&info, in, &info.file_shdrs[s->sh_link]) < 0 || syms_load_syms(&info, in, s) < 0) ret = -1; return ret; }
static int parse_cmdline_args(int argc, char **argv, struct cmdline_args *args) { enum { LOPT_HELP = 0x100, LOPT_FET_LIST, LOPT_FET_FORCE_ID, LOPT_FET_SKIP_CLOSE, LOPT_USB_LIST, LOPT_VERSION, LOPT_LONG_PASSWORD, LOPT_FORCE_RESET, LOPT_ALLOW_FW_UPDATE, LOPT_REQUIRE_FW_UPDATE, LOPT_EMBEDDED, LOPT_BSL_ENTRY_SEQUENCE, LOPT_BSL_GPIO_RTS, LOPT_BSL_GPIO_DTR, }; static const struct option longopts[] = { {"help", 0, 0, LOPT_HELP}, {"fet-list", 0, 0, LOPT_FET_LIST}, {"fet-force-id", 1, 0, LOPT_FET_FORCE_ID}, {"fet-skip-close", 0, 0, LOPT_FET_SKIP_CLOSE}, {"usb-list", 0, 0, LOPT_USB_LIST}, {"version", 0, 0, LOPT_VERSION}, {"long-password", 0, 0, LOPT_LONG_PASSWORD}, {"force-reset", 0, 0, LOPT_FORCE_RESET}, {"allow-fw-update", 0, 0, LOPT_ALLOW_FW_UPDATE}, {"require-fw-update", 1, 0, LOPT_REQUIRE_FW_UPDATE}, {"embedded", 0, 0, LOPT_EMBEDDED}, {"bsl-entry-sequence", 1, 0, LOPT_BSL_ENTRY_SEQUENCE}, {"bsl-gpio-rts", 1, 0, LOPT_BSL_GPIO_RTS}, {"bsl-gpio-dtr", 1, 0, LOPT_BSL_GPIO_DTR}, {NULL, 0, 0, 0} }; int opt; int want_usb = 0; while ((opt = getopt_long(argc, argv, "d:jv:nU:s:qC:", longopts, NULL)) >= 0) switch (opt) { case 'C': args->alt_config = optarg; break; case 'q': { static const union opdb_value v = { .boolean = 1 }; opdb_set("quiet", &v); } break; case LOPT_BSL_ENTRY_SEQUENCE: args->devarg.bsl_entry_seq = optarg; break; case LOPT_BSL_GPIO_RTS: args->devarg.bsl_gpio_used = 1; args->devarg.bsl_gpio_rts = atoi ( optarg ); break; case LOPT_BSL_GPIO_DTR: args->devarg.bsl_gpio_used = 1; args->devarg.bsl_gpio_dtr = atoi ( optarg ); break; case LOPT_EMBEDDED: args->flags |= OPT_EMBEDDED; break; case LOPT_ALLOW_FW_UPDATE: args->devarg.flags |= DEVICE_FLAG_DO_FWUPDATE; break; case LOPT_USB_LIST: usb_init(); usb_find_busses(); usb_find_devices(); usbutil_list(); exit(0); case 'd': args->devarg.path = optarg; args->devarg.flags |= DEVICE_FLAG_TTY; break; case LOPT_REQUIRE_FW_UPDATE: args->devarg.require_fwupdate = optarg; break; case 'U': args->devarg.path = optarg; want_usb = 1; break; case 's': args->devarg.requested_serial = optarg; break; case LOPT_FET_LIST: exit(list_devices()); case LOPT_FET_FORCE_ID: args->devarg.forced_chip_id = optarg; break; case LOPT_FET_SKIP_CLOSE: args->devarg.flags |= DEVICE_FLAG_SKIP_CLOSE; break; case LOPT_HELP: usage(argv[0]); exit(0); case LOPT_VERSION: printc("%s", version_text); printc("%s", chipinfo_copyright()); exit(0); case 'v': args->devarg.vcc_mv = atoi(optarg); break; case 'j': args->devarg.flags |= DEVICE_FLAG_JTAG; break; case 'n': args->flags |= OPT_NO_RC; break; case LOPT_LONG_PASSWORD: args->devarg.flags |= DEVICE_FLAG_LONG_PW; break; case LOPT_FORCE_RESET: args->devarg.flags |= DEVICE_FLAG_FORCE_RESET; break; case '?': printc_err("Try --help for usage information.\n"); return -1; } if (want_usb && (args->devarg.flags & DEVICE_FLAG_TTY)) { printc_err("You can't simultaneously specify a serial and " "a USB device.\n"); return -1; } if (optind >= argc) { printc_err("You need to specify a driver. Try --help for " "a list.\n"); return -1; } args->driver_name = argv[optind]; optind++; return 0; } int setup_driver(struct cmdline_args *args) { int i; i = 0; while (i < ARRAY_LEN(driver_table) && strcasecmp(driver_table[i]->name, args->driver_name)) i++; if (i >= ARRAY_LEN(driver_table)) { printc_err("Unknown driver: %s. Try --help for a list.\n", args->driver_name); return -1; } if (stab_init() < 0) return -1; device_default = driver_table[i]->open(&args->devarg); if (!device_default) { stab_exit(); return -1; } return 0; }
int main(int argc, char **argv) { struct cmdline_args args = {0}; int ret = 0; setvbuf(stderr, NULL, _IOFBF, 0); setvbuf(stdout, NULL, _IOFBF, 0); opdb_reset(); ctrlc_init(); args.devarg.vcc_mv = 3000; args.devarg.requested_serial = NULL; if (parse_cmdline_args(argc, argv, &args) < 0) goto fail_parse; if (args.flags & OPT_EMBEDDED) input_module = &input_async; if (input_module->init() < 0) goto fail_input; output_set_embedded(args.flags & OPT_EMBEDDED); if (sockets_init() < 0) { ret = -1; goto fail_sockets; } printc_dbg("%s", version_text); printc_dbg("%s\n", chipinfo_copyright()); if (setup_driver(&args) < 0) { ret = -1; goto fail_driver; } if (device_probe_id(device_default, args.devarg.forced_chip_id) < 0) printc_err("warning: device ID probe failed\n"); simio_init(); if (!(args.flags & OPT_NO_RC)) process_rc_file(args.alt_config); /* Process commands */ if (optind < argc) { while (optind < argc) { if (process_command(argv[optind++]) < 0) { ret = -1; break; } } } else { reader_loop(); } simio_exit(); device_destroy(); stab_exit(); fail_driver: sockets_exit(); fail_sockets: input_module->exit(); fail_input: fail_parse: /* We need to do this on Windows, because in embedded mode we * may still have a running background thread for input. If so, * returning from main() won't cause the process to terminate. */ #if defined(__CYGWIN__) cygwin_internal(CW_EXIT_PROCESS, (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE, 1); #elif defined(__Windows__) ExitProcess(ret); #endif return ret; }