static int prog_feed(void *user_data, uint16_t addr, const uint8_t *data, int len) { struct prog_data *prog = (struct prog_data *)user_data; /* Flush if this section is discontiguous */ if (prog->len && prog->addr + prog->len != addr && prog_flush(prog) < 0) return -1; if (!prog->len) prog->addr = addr; /* Add the buffer in piece by piece, flushing when it gets * full. */ while (len) { int count = sizeof(prog->buf) - prog->len; if (count > len) count = len; if (!count) { if (prog_flush(prog) < 0) return -1; } else { memcpy(prog->buf + prog->len, data, count); prog->len += count; data += count; len -= count; } } return 0; }
int prog_feed(struct prog_data *prog, const struct binfile_chunk *ch) { const char *section = ch->name ? ch->name : ""; const uint8_t *data = ch->data; int len = ch->len; /* Flush if this chunk is discontiguous, or in a different * section. */ if (prog->len && ((prog->addr + prog->len != ch->addr) || strcmp(prog->section, section))) { if (prog_flush(prog) < 0) return -1; } if (!prog->len) { prog->addr = ch->addr; strncpy(prog->section, section, sizeof(prog->section)); prog->section[sizeof(prog->section) - 1] = 0; } /* Add the buffer in piece by piece, flushing when it gets * full. */ while (len) { int count = sizeof(prog->buf) - prog->len; if (count > len) count = len; if (!count) { if (prog_flush(prog) < 0) return -1; } else { memcpy(prog->buf + prog->len, data, count); prog->len += count; data += count; len -= count; } } return 0; }
static int cmd_prog(cproc_t cp, char **arg) { device_t dev = cproc_device(cp); stab_t stab = cproc_stab(cp); FILE *in; struct prog_data prog; if (cproc_prompt_abort(cp, CPROC_MODIFY_SYMS)) return 0; in = fopen(*arg, "r"); if (!in) { fprintf(stderr, "prog: %s: %s\n", *arg, strerror(errno)); return -1; } if (dev->ctl(dev, DEVICE_CTL_HALT) < 0) { fclose(in); return -1; } prog_init(&prog, dev); if (binfile_extract(in, prog_feed, &prog) < 0) { fclose(in); return -1; } if (binfile_info(in) & BINFILE_HAS_SYMS) { stab_clear(stab); binfile_syms(in, stab); } fclose(in); if (prog_flush(&prog) < 0) return -1; if (dev->ctl(dev, DEVICE_CTL_RESET) < 0) { fprintf(stderr, "prog: failed to reset after programming\n"); return -1; } cproc_unmodify(cp, CPROC_MODIFY_SYMS); return 0; }