Esempio n. 1
0
int ty_thread_create(ty_thread *thread, ty_thread_func *f, void *udata)
{
    struct thread_context ctx;
    int r;

    ctx.thread = thread;
    ctx.f = f;
    ctx.udata = udata;

    ctx.ev = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!ctx.ev) {
        r = ty_error(TY_ERROR_SYSTEM, "CreateEvent() failed: %s", ty_win32_strerror(0));
        goto cleanup;
    }

    thread->h = (HANDLE)_beginthreadex(NULL, 0, thread_proc, &ctx, 0,
                                       (unsigned int *)&thread->thread_id);
    if (!thread->h) {
        r = ty_error(TY_ERROR_SYSTEM, "_beginthreadex() failed: %s", ty_win32_strerror(0));
        goto cleanup;
    }

    WaitForSingleObject(ctx.ev, INFINITE);

    r = 0;
cleanup:
    if (ctx.ev)
        CloseHandle(ctx.ev);
    return r;
}
Esempio n. 2
0
int ty_firmware_load(const char *filename, const char *format_name, ty_firmware **rfw)
{
    assert(filename);
    assert(rfw);

    const ty_firmware_format *format = NULL;

    if (format_name) {
        for (unsigned int i = 0; i < ty_firmware_formats_count; i++) {
            if (strcasecmp(ty_firmware_formats[i].name, format_name) == 0) {
                format = &ty_firmware_formats[i];
                break;
            }
        }
        if (!format)
            return ty_error(TY_ERROR_UNSUPPORTED, "Firmware file format '%s' unknown", format_name);
    } else {
        const char *ext = strrchr(filename, '.');
        if (!ext)
            return ty_error(TY_ERROR_UNSUPPORTED, "Firmware '%s' has no file extension", filename);

        for (unsigned int i = 0; i < ty_firmware_formats_count; i++) {
            if (strcmp(ty_firmware_formats[i].ext, ext) == 0) {
                format = &ty_firmware_formats[i];
                break;
            }
        }
        if (!format)
            return ty_error(TY_ERROR_UNSUPPORTED, "Firmware '%s' uses unrecognized file format",
                            filename);
    }

    return (*format->load)(filename, rfw);
}
Esempio n. 3
0
int _ty_firmware_load_ihex(ty_firmware *fw)
{
    assert(fw);

    struct parser_context ctx = {0};
    FILE *fp = NULL;
    char buf[1024];
    int r;

    ctx.fw = fw;

#ifdef _WIN32
    fp = fopen(fw->filename, "r");
#else
    fp = fopen(fw->filename, "re");
#endif
    if (!fp) {
        switch (errno) {
        case EACCES:
            r = ty_error(TY_ERROR_ACCESS, "Permission denied for '%s'", fw->filename);
            break;
        case EIO:
            r = ty_error(TY_ERROR_IO, "I/O error while opening '%s' for reading", fw->filename);
            break;
        case ENOENT:
        case ENOTDIR:
            r = ty_error(TY_ERROR_NOT_FOUND, "File '%s' does not exist", fw->filename);
            break;

        default:
            r = ty_error(TY_ERROR_SYSTEM, "fopen('%s') failed: %s", fw->filename, strerror(errno));
            break;
        }
        goto cleanup;
    }

    do {
        if (!fgets(buf, sizeof(buf), fp)) {
            if (feof(fp)) {
                r = parse_error(&ctx);
            } else {
                r = ty_error(TY_ERROR_IO, "I/O error while reading '%s'", fw->filename);
            }
            goto cleanup;
        }
        ctx.line++;

        // Returns 1 when EOF record is detected
        r = parse_line(&ctx, buf);
        if (r < 0)
            goto cleanup;
    } while (!r);

    r = 0;
cleanup:
    if (fp)
        fclose(fp);
    return r;
}
Esempio n. 4
0
static int do_stat(int fd, const char *path, ty_file_info *info, bool follow)
{
    struct stat sb;
    int r;

#ifdef HAVE_FSTATAT
    r = fstatat(fd, path, &sb, !follow ? AT_SYMLINK_NOFOLLOW : 0);
#else
    if (follow) {
        r = stat(path, &sb);
    } else {
        r = lstat(path, &sb);
    }
#endif
    if (r < 0) {
        switch (errno) {
        case EACCES:
            return ty_error(TY_ERROR_ACCESS, "Permission denied for '%s'", path);
        case EIO:
            return ty_error(TY_ERROR_IO, "I/O error while stating '%s'", path);
        case ENOENT:
            return ty_error(TY_ERROR_NOT_FOUND, "Path '%s' does not exist", path);
        case ENOTDIR:
            return ty_error(TY_ERROR_NOT_FOUND, "Part of '%s' is not a directory", path);
        }
        return ty_error(TY_ERROR_SYSTEM, "Failed to stat '%s': %s", path, strerror(errno));
    }

    if (S_ISDIR(sb.st_mode)) {
        info->type = TY_FILE_DIRECTORY;
    } else if (S_ISREG(sb.st_mode)) {
        info->type = TY_FILE_REGULAR;
#ifdef S_ISLNK
    } else if (S_ISLNK(sb.st_mode)) {
        info->type = TY_FILE_LINK;
#endif
    } else {
        info->type = TY_FILE_SPECIAL;
    }

    info->size = (uint64_t)sb.st_size;
#if defined(HAVE_STAT_MTIM)
    info->mtime = (uint64_t)sb.st_mtim.tv_sec * 1000 + (uint64_t)sb.st_mtim.tv_nsec / 1000000;
#elif defined(HAVE_STAT_MTIMESPEC)
    info->mtime = (uint64_t)sb.st_mtimespec.tv_sec * 1000 + (uint64_t)sb.st_mtimespec.tv_nsec / 1000000;
#else
    info->mtime = (uint64_t)sb.st_mtime * 1000;
#endif

    return 0;
}
Esempio n. 5
0
static int redirect_stdout(int *routfd)
{
    int outfd, r;

    outfd = dup(STDOUT_FILENO);
    if (outfd < 0)
        return ty_error(TY_ERROR_SYSTEM, "dup() failed: %s", strerror(errno));

    r = dup2(STDERR_FILENO, STDOUT_FILENO);
    if (r < 0)
        return ty_error(TY_ERROR_SYSTEM, "dup2() failed: %s", strerror(errno));

    *routfd = outfd;
    return 0;
}
Esempio n. 6
0
static int start_stdin_thread(void)
{
    input_available = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!input_available)
        return ty_error(TY_ERROR_SYSTEM, "CreateEvent() failed: %s", ty_win32_strerror(0));

    input_processed = CreateEvent(NULL, TRUE, TRUE, NULL);
    if (!input_processed)
        return ty_error(TY_ERROR_SYSTEM, "CreateEvent() failed: %s", ty_win32_strerror(0));

    input_thread = (HANDLE)_beginthreadex(NULL, 0, stdin_thread, NULL, 0, NULL);
    if (!input_thread)
        return ty_error(TY_ERROR_SYSTEM, "_beginthreadex() failed: %s", ty_win32_strerror(0));

    return 0;
}
Esempio n. 7
0
static unsigned int __stdcall stdin_thread(void *udata)
{
    TY_UNUSED(udata);

    DWORD len;
    BOOL success;
    int r;

    while (input_run) {
        WaitForSingleObject(input_processed, INFINITE);
        ResetEvent(input_processed);

        success = ReadFile(GetStdHandle(STD_INPUT_HANDLE), input_line, sizeof(input_line), &len, NULL);
        if (!success) {
            r = ty_error(TY_ERROR_IO, "I/O error while reading standard input");
            goto error;
        }
        if (!len) {
            r = 0;
            goto error;
        }

        input_ret = (ssize_t)len;
        SetEvent(input_available);
    }

    return 0;

error:
    input_ret = r;
    SetEvent(input_available);
    return 0;
}
Esempio n. 8
0
int ty_poll(const ty_descriptor_set *set, int timeout)
{
    assert(set);
    assert(set->count);
    assert(set->count <= 64);

    fd_set fds;
    uint64_t start;
    struct timeval tv;
    int r;

    FD_ZERO(&fds);
    for (unsigned int i = 0; i < set->count; i++)
        FD_SET(set->desc[i], &fds);

    start = ty_millis();
restart:
    if (timeout >= 0) {
        tv.tv_sec = timeout / 1000;
        tv.tv_usec = (timeout % 1000) * 1000;
    }

    r = select(FD_SETSIZE, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
    if (r < 0) {
        switch (errno) {
        case EINTR:
            timeout = ty_adjust_timeout(timeout, start);
            goto restart;
        case ENOMEM:
            return ty_error(TY_ERROR_MEMORY, NULL);
        }
        return ty_error(TY_ERROR_SYSTEM, "poll() failed: %s", strerror(errno));
    }
    if (!r)
        return 0;

    for (unsigned int i = 0; i < set->count; i++) {
        if (FD_ISSET(set->desc[i], &fds))
            return set->id[i];
    }

    assert(false);
    __builtin_unreachable();
}
Esempio n. 9
0
int ty_terminal_setup(int flags)
{
    struct termios tio;
    int r;

    r = tcgetattr(STDIN_FILENO, &tio);
    if (r < 0) {
        if (errno == ENOTTY)
            return ty_error(TY_ERROR_UNSUPPORTED, "Not a terminal");
        return ty_error(TY_ERROR_SYSTEM, "tcgetattr() failed: %s", strerror(errno));
    }

    if (!saved_termios) {
        orig_termios = tio;
        saved_termios = true;

        atexit(ty_terminal_restore);
    }

    if (flags & TY_TERMINAL_RAW) {
        cfmakeraw(&tio);
        tio.c_oflag |= OPOST | ONLCR;
        tio.c_lflag |= ISIG;
    } else {
        tio.c_iflag = TTYDEF_IFLAG;
        tio.c_oflag = TTYDEF_OFLAG;
        tio.c_lflag = TTYDEF_LFLAG;
        tio.c_cflag = TTYDEF_CFLAG;
    }
    tio.c_cc[VMIN] = 1;
    tio.c_cc[VTIME] = 0;

    tio.c_lflag |= ECHO;
    if (flags & TY_TERMINAL_SILENT)
        tio.c_lflag &= (unsigned int)~ECHO;

    r = tcsetattr(STDIN_FILENO, TCSADRAIN, &tio);
    if (r < 0)
        return ty_error(TY_ERROR_SYSTEM, "tcsetattr() failed: %s", strerror(errno));

    return 0;
}
Esempio n. 10
0
int ty_poll(const ty_descriptor_set *set, int timeout)
{
    assert(set);
    assert(set->count);
    assert(set->count <= 64);

    struct pollfd pfd[64];
    uint64_t start;
    int r;

    for (unsigned int i = 0; i < set->count; i++) {
        pfd[i].events = POLLIN;
        pfd[i].fd = set->desc[i];
    }

    if (timeout < 0)
        timeout = -1;

    start = ty_millis();
restart:
    r = poll(pfd, (nfds_t)set->count, ty_adjust_timeout(timeout, start));
    if (r < 0) {
        switch (errno) {
        case EINTR:
            goto restart;
        case ENOMEM:
            return ty_error(TY_ERROR_MEMORY, NULL);
        }
        return ty_error(TY_ERROR_SYSTEM, "poll() failed: %s", strerror(errno));
    }
    if (!r)
        return 0;

    for (unsigned int i = 0; i < set->count; i++) {
        if (pfd[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL))
            return set->id[i];
    }

    assert(false);
    __builtin_unreachable();
}
Esempio n. 11
0
unsigned short getindex()
{
    unsigned char ch;

    ch = getbyte();

    if (ch != OLF_INDEX) {
        ty_error(ch, L"Expecting index leaf");
    }

    return(getshort());
}
Esempio n. 12
0
int ty_firmware_expand_image(ty_firmware *fw, size_t size)
{
    if (size > fw->alloc_size) {
        uint8_t *tmp;
        size_t alloc_size;

        if (size > TY_FIRMWARE_MAX_SIZE)
            return ty_error(TY_ERROR_RANGE, "Firmware too big (max %u bytes) in '%s'",
                            TY_FIRMWARE_MAX_SIZE, fw->filename);

        alloc_size = (size + (FIRMWARE_STEP_SIZE - 1)) / FIRMWARE_STEP_SIZE * FIRMWARE_STEP_SIZE;
        tmp = realloc(fw->image, alloc_size);
        if (!tmp)
            return ty_error(TY_ERROR_MEMORY, NULL);
        fw->image = tmp;
        fw->alloc_size = alloc_size;
    }
    fw->size = size;

    return 0;
}
Esempio n. 13
0
char *getname()
{
    unsigned char ch;

    ch = getbyte();

    if (ch != OLF_STRING) {
        ty_error(ch, L"Expecting string leaf");
    }

    return(getstring());
}
Esempio n. 14
0
int ty_terminal_setup(int flags)
{
    HANDLE handle;
    DWORD mode;
    BOOL r;

    handle = GetStdHandle(STD_INPUT_HANDLE);
    if (handle == INVALID_HANDLE_VALUE)
        return ty_error(TY_ERROR_SYSTEM, "GetStdHandle(STD_INPUT_HANDLE) failed");

    r = GetConsoleMode(handle, &mode);
    if (!r) {
        if (GetLastError() == ERROR_INVALID_HANDLE)
            return ty_error(TY_ERROR_UNSUPPORTED, "Not a terminal");
        return ty_error(TY_ERROR_SYSTEM, "GetConsoleMode(STD_INPUT_HANDLE) failed: %s",
                        ty_win32_strerror(0));
    }

    if (!saved_console_mode) {
        orig_console_mode = mode;
        saved_console_mode = true;

        atexit(ty_terminal_restore);
    }

    mode |= ENABLE_PROCESSED_INPUT;

    mode &= (DWORD)~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
    if (!(flags & TY_TERMINAL_RAW))
        mode |= ENABLE_LINE_INPUT;
    if (!(flags & TY_TERMINAL_SILENT))
        mode |= ENABLE_ECHO_INPUT;

    r = SetConsoleMode(handle, mode);
    if (!r)
        return ty_error(TY_ERROR_SYSTEM, "SetConsoleMode(STD_INPUT_HANDLE) failed: %s",
                        ty_win32_strerror(0));

    return 0;
}
Esempio n. 15
0
int ty_firmware_new(const char *filename, ty_firmware **rfw)
{
    assert(filename);
    assert(rfw);

    ty_firmware *fw;
    int r;

    fw = calloc(1, sizeof(ty_firmware));
    if (!fw) {
        r = ty_error(TY_ERROR_MEMORY, NULL);
        goto error;
    }
    fw->refcount = 1;

    fw->filename = strdup(filename);
    if (!fw->filename) {
        r = ty_error(TY_ERROR_MEMORY, NULL);
        goto error;
    }

    if (!fw->name) {
        fw->name = strdup(get_basename(filename));
        if (!fw->name) {
            r = ty_error(TY_ERROR_MEMORY, NULL);
            goto error;
        }
    }

    *rfw = fw;
    return 0;

error:
    ty_firmware_unref(fw);
    return r;
}
Esempio n. 16
0
long getvalue()
{
    unsigned char ch;
    char c;
    short s;

    ch = getbyte();
    if (ch < 128) {
        return (ch);
    }
    switch (ch & 0xff) {
        case OLF_STRING:
            s = getbyte();
            dump_hex(s, true);
            return (0);

        case OLF_1_SIGNED:
                // Fix for vax compiler bug, doesn't cast procedure return
                // values correctly

            c = getbyte();
            return (c);

        case OLF_2_SIGNED:
            s = getshort();
            return (s);

        case OLF_2_UNSIGNED:
            return (getshort() & 0xffff);

        case OLF_4_UNSIGNED:
        case OLF_4_SIGNED:
            return (getlong());

        case OLF_8_UNSIGNED:
        case OLF_8_SIGNED:
            StdOutPuts(L"??? 8 byte values not handled presently\n");
            dump_hex(8, true);
            return(0);

        default:
            ty_error(ch, L"Expecting numeric leaf");
            return (0);
    }
}
Esempio n. 17
0
int ty_poll(const ty_descriptor_set *set, int timeout)
{
    assert(set);
    assert(set->count);
    assert(set->count <= 64);

    DWORD ret = WaitForMultipleObjects((DWORD)set->count, set->desc, FALSE,
                                       timeout < 0 ? INFINITE : (DWORD)timeout);
    switch (ret) {
    case WAIT_FAILED:
        return ty_error(TY_ERROR_SYSTEM, "WaitForMultipleObjects() failed: %s",
                        ty_win32_strerror(0));
    case WAIT_TIMEOUT:
        return 0;
    }

    return set->id[ret - WAIT_OBJECT_0];
}
Esempio n. 18
0
void ty_delay(unsigned int ms)
{
    struct timespec t, rem;
    int r;

    t.tv_sec = (int)(ms / 1000);
    t.tv_nsec = (int)((ms % 1000) * 1000000);

    do {
        r = nanosleep(&t, &rem);
        if (r < 0) {
            if (errno != EINTR) {
                ty_error(TY_ERROR_SYSTEM, "nanosleep() failed: %s", strerror(errno));
                return;
            }

            t = rem;
        }
    } while (r);
}
Esempio n. 19
0
int ty_stat(const char *path, ty_file_info *info, bool follow)
{
    TY_UNUSED(follow);

    assert(path && path[0]);
    assert(info);

    HANDLE h;
    BY_HANDLE_FILE_INFORMATION attr;
    int r;

    // FIXME: check error handling
    h = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (h == INVALID_HANDLE_VALUE) {
        switch (GetLastError()) {
        case ERROR_ACCESS_DENIED:
            return ty_error(TY_ERROR_ACCESS, "Permission denied for '%s'", path);
        case ERROR_NOT_READY:
            return ty_error(TY_ERROR_IO, "I/O error while stating '%s'", path);
        case ERROR_FILE_NOT_FOUND:
            return ty_error(TY_ERROR_NOT_FOUND, "Path '%s' does not exist", path);
        case ERROR_PATH_NOT_FOUND:
            return ty_error(TY_ERROR_NOT_FOUND, "Part of '%s' is not a directory", path);
        }
        // Let's lie a little, error will be clearer this way
        return ty_error(TY_ERROR_SYSTEM, "GetFileAttributesEx('%s') failed: %s", path, ty_win32_strerror(0));
    }

    r = GetFileInformationByHandle(h, &attr);
    if (!r)
        return ty_error(TY_ERROR_SYSTEM, "GetFileInformationByHandle('%s') failed: %s", path, ty_win32_strerror(0));

    if (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        info->type = TY_FILE_DIRECTORY;
    } else if (attr.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) {
        info->type = TY_FILE_SPECIAL;
    } else {
        info->type = TY_FILE_REGULAR;
    }

    info->size = ((uint64_t)attr.nFileSizeHigh << 32) | attr.nFileSizeLow;
    info->mtime = filetime_to_unix_time(&attr.ftLastWriteTime);

    return 0;
}
Esempio n. 20
0
int ty_cond_init(ty_cond *cond)
{
    static bool init;
    static InitializeConditionVariable_func *InitializeConditionVariable_;

    if (!init) {
        HANDLE kernel32 = GetModuleHandle("kernel32.dll");

        // Condition Variables appeared on Vista, emulate them on Windows XP
        InitializeConditionVariable_ = (InitializeConditionVariable_func *)GetProcAddress(kernel32, "InitializeConditionVariable");
        if (InitializeConditionVariable_) {
            WakeConditionVariable_ = (WakeConditionVariable_func *)GetProcAddress(kernel32, "WakeConditionVariable");
            WakeAllConditionVariable_ = (WakeAllConditionVariable_func *)GetProcAddress(kernel32, "WakeAllConditionVariable");
            SleepConditionVariableCS_ = (SleepConditionVariableCS_func *)GetProcAddress(kernel32, "SleepConditionVariableCS");
        } else {
            WakeConditionVariable_ = WakeConditionVariable_fallback;
            WakeAllConditionVariable_ = WakeAllConditionVariable_fallback;
            SleepConditionVariableCS_ = SleepConditionVariableCS_fallback;
        }

        init = true;
    }

    if (InitializeConditionVariable_) {
        InitializeConditionVariable_((CONDITION_VARIABLE *)&cond->cv);
    } else {
        memset(cond, 0, sizeof(*cond));
        cond->xp.ev = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!cond->xp.ev)
            return ty_error(TY_ERROR_SYSTEM, "CreateEvent() failed: %s", ty_win32_strerror(0));
        InitializeCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);
    }
    cond->init = true;

    return 0;
}
Esempio n. 21
0
static int parse_error(struct parser_context *ctx)
{
    return ty_error(TY_ERROR_PARSE, "IHEX parse error on line %u in '%s'", ctx->line,
                    ctx->fw->filename);
}
Esempio n. 22
0
static int parse_line(struct parser_context *ctx, const char *line)
{
    unsigned int length, type;
    uint32_t address;
    uint8_t checksum;

    ctx->ptr = line;
    ctx->sum = 0;
    ctx->error = false;

    // Empty lines are probably OK
    if (*ctx->ptr++ != ':')
        return 1;
    if (strlen(ctx->ptr) < 11)
        return TY_ERROR_PARSE;

    length = parse_hex_byte(ctx, true);
    address = parse_hex_short(ctx);
    type = parse_hex_byte(ctx, true);

    if (ctx->error)
        return TY_ERROR_PARSE;

    switch (type) {
    case 0: // data record
        address += ctx->base_offset;
        if (address + length > ctx->f->size) {
            ctx->f->size = address + length;

            if (ctx->f->size > tyb_firmware_max_size)
                return ty_error(TY_ERROR_RANGE, "Firmware too big (max %zu bytes)",
                                tyb_firmware_max_size);
        }

        for (unsigned int i = 0; i < length; i++)
            ctx->f->image[address + i] = parse_hex_byte(ctx, true);
        break;

    case 1: // EOF record
        if (length > 0)
            return TY_ERROR_PARSE;
        return 0;

    case 2: // extended segment address record
        if (length != 2)
            return TY_ERROR_PARSE;
        ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 4;
        break;
    case 3: // start segment address record
        break;

    case 4: // extended linear address record
        if (length != 2)
            return TY_ERROR_PARSE;
        ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 16;
        break;
    case 5: // start linear address record
        break;

    default:
        return TY_ERROR_PARSE;
    }

    // Don't checksum the checksum :)
    checksum = parse_hex_byte(ctx, false);

    if (ctx->error)
        return TY_ERROR_PARSE;

    if (((ctx->sum & 0xFF) + (checksum & 0xFF)) & 0xFF)
        return TY_ERROR_PARSE;

    // 1 to continue, 0 to stop (EOF record) and negative for errors
    return 1;
}
Esempio n. 23
0
int ty_firmware_load(const char *filename, const char *format_name, ty_firmware **rfw)
{
    assert(filename);
    assert(rfw);

    const ty_firmware_format *format;
    ty_firmware *fw = NULL;
    int r;

    if (format_name) {
        for (format = ty_firmware_formats; format->name; format++) {
            if (strcasecmp(format->name, format_name) == 0)
                break;
        }
        if (!format->name) {
            r = ty_error(TY_ERROR_UNSUPPORTED, "Firmware file format '%s' unknown", format_name);
            goto error;
        }
    } else {
        const char *ext = strrchr(filename, '.');
        if (!ext) {
            r = ty_error(TY_ERROR_UNSUPPORTED, "Firmware '%s' has no file extension", filename);
            goto error;
        }

        for (format = ty_firmware_formats; format->name; format++) {
            if (strcmp(format->ext, ext) == 0)
                break;
        }
        if (!format->name) {
            r = ty_error(TY_ERROR_UNSUPPORTED, "Firmware '%s' uses unrecognized file format", filename);
            goto error;
        }
    }

    fw = malloc(sizeof(ty_firmware) + strlen(filename) + 1);
    if (!fw) {
        r = ty_error(TY_ERROR_MEMORY, NULL);
        goto error;
    }
    memset(fw, 0, sizeof(*fw));
    fw->refcount = 1;
    strcpy(fw->filename, filename);

    r = (*format->load)(fw);
    if (r < 0)
        goto error;

    if (!fw->name) {
        fw->name = strdup(get_basename(filename));
        if (!fw->name) {
            r = ty_error(TY_ERROR_MEMORY, NULL);
            goto error;
        }
    }

    *rfw = fw;
    return 0;

error:
    ty_firmware_unref(fw);
    return r;
}
Esempio n. 24
0
int _tyb_firmware_load_ihex(const char *filename, tyb_firmware **rfirmware)
{
    assert(rfirmware);
    assert(filename);

    struct parser_context ctx = {0};
    FILE *fp = NULL;
    char buf[1024];
    int r;

    ctx.f = malloc(sizeof(tyb_firmware) + tyb_firmware_max_size);
    if (!ctx.f)
        return ty_error(TY_ERROR_MEMORY, NULL);
    memset(ctx.f, 0, sizeof(*ctx.f));
    memset(ctx.f->image, 0xFF, tyb_firmware_max_size);

#ifdef _WIN32
    fp = fopen(filename, "r");
#else
    fp = fopen(filename, "re");
#endif
    if (!fp) {
        switch (errno) {
        case EACCES:
            r = ty_error(TY_ERROR_ACCESS, "Permission denied for '%s'", filename);
            break;
        case EIO:
            r = ty_error(TY_ERROR_IO, "I/O error while opening '%s' for reading", filename);
            break;
        case ENOENT:
        case ENOTDIR:
            r = ty_error(TY_ERROR_NOT_FOUND, "File '%s' does not exist", filename);
            break;

        default:
            r = ty_error(TY_ERROR_SYSTEM, "fopen('%s') failed: %s", filename, strerror(errno));
            break;
        }
        goto cleanup;
    }

    while (!feof(fp)) {
        if (!fgets(buf, sizeof(buf), fp))
            break;
        ctx.line++;

        r = parse_line(&ctx, buf);
        if (r < 0) {
            if (r == TY_ERROR_PARSE)
                ty_error(r, "Parse error (Intel HEX) on line %u in '%s'\n", ctx.line, filename);
            goto cleanup;
        }

        // Either EOF record or real EOF will do, albeit the first is probably
        // better (guarantees the file is complete)
        if (r == 0 || feof(fp))
            break;
    }

    *rfirmware = ctx.f;
    ctx.f = NULL;

    r = 0;
cleanup:
    if (fp)
        fclose(fp);
    free(ctx.f);
    return r;
}
Esempio n. 25
0
static int loop(ty_board *board, int outfd)
{
    ty_descriptor_set set = {0};
    int timeout;
    char buf[BUFFER_SIZE];
    ssize_t r;

restart:
    r = ty_board_serial_set_attributes(board, device_rate, device_flags);
    if (r < 0)
        return (int)r;

    r = fill_descriptor_set(&set, board);
    if (r < 0)
        return (int)r;
    timeout = -1;

    ty_log(TY_LOG_INFO, "Monitoring '%s'", ty_board_get_tag(board));

    while (true) {
        if (!set.count)
            return 0;

        r = ty_poll(&set, timeout);
        if (r < 0)
            return (int)r;

        switch (r) {
        case 0:
            return 0;

        case 1:
            r = ty_monitor_refresh(ty_board_get_monitor(board));
            if (r < 0)
                return (int)r;

            if (!ty_board_has_capability(board, TY_BOARD_CAPABILITY_SERIAL)) {
                if (!reconnect)
                    return 0;

                ty_log(TY_LOG_INFO, "Waiting for '%s'...", ty_board_get_tag(board));
                r = ty_board_wait_for(board, TY_BOARD_CAPABILITY_SERIAL, -1);
                if (r < 0)
                    return (int)r;

                goto restart;
            }

            break;

        case 2:
            r = ty_board_serial_read(board, buf, sizeof(buf), 0);
            if (r < 0) {
                if (r == TY_ERROR_IO && reconnect) {
                    timeout = ERROR_IO_TIMEOUT;
                    ty_descriptor_set_remove(&set, 2);
                    ty_descriptor_set_remove(&set, 3);
                    break;
                }
                return (int)r;
            }

#ifdef _WIN32
            r = write(outfd, buf, (unsigned int)r);
#else
            r = write(outfd, buf, (size_t)r);
#endif
            if (r < 0) {
                if (errno == EIO)
                    return ty_error(TY_ERROR_IO, "I/O error on standard output");
                return ty_error(TY_ERROR_IO, "Failed to write to standard output: %s",
                                strerror(errno));
            }

            break;

        case 3:
#ifdef _WIN32
            if (input_available) {
                if (input_ret < 0)
                    return (int)input_ret;

                memcpy(buf, input_line, (size_t)input_ret);
                r = input_ret;

                ResetEvent(input_available);
                SetEvent(input_processed);
            } else {
                r = read(STDIN_FILENO, buf, sizeof(buf));
            }
#else
            r = read(STDIN_FILENO, buf, sizeof(buf));
#endif
            if (r < 0) {
                if (errno == EIO)
                    return ty_error(TY_ERROR_IO, "I/O error on standard input");
                return ty_error(TY_ERROR_IO, "Failed to read from standard input: %s",
                                strerror(errno));
            }
            if (!r) {
                if (timeout_eof >= 0) {
                    /* EOF reached, don't listen to stdin anymore, and start timeout to give some
                       time for the device to send any data before closing down. */
                    timeout = timeout_eof;
                    ty_descriptor_set_remove(&set, 1);
                    ty_descriptor_set_remove(&set, 3);
                }
                break;
            }

#ifdef _WIN32
            if (fake_echo) {
                r = write(outfd, buf, (unsigned int)r);
                if (r < 0)
                    return (int)r;
            }
#endif

            r = ty_board_serial_write(board, buf, (size_t)r);
            if (r < 0) {
                if (r == TY_ERROR_IO && reconnect) {
                    timeout = ERROR_IO_TIMEOUT;
                    ty_descriptor_set_remove(&set, 2);
                    ty_descriptor_set_remove(&set, 3);
                    break;
                }
                return (int)r;
            }

            break;
        }
    }
}