Example #1
0
static int parse_line(struct parser_context *ctx, const char *line)
{
    unsigned int length, type;
    uint32_t address;
    uint8_t checksum;
    int r;

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

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

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

    if (ctx->error)
        return parse_error(ctx);

    switch (type) {
    case 0: // data record
        address += ctx->base_offset;
        r = _ty_firmware_expand_image(ctx->fw, address + length);
        if (r < 0)
            return r;
        for (unsigned int i = 0; i < length; i++)
            ctx->fw->image[address + i] = parse_hex_byte(ctx, true);
        break;

    case 1: // EOF record
        if (length > 0)
            return parse_error(ctx);
        break;

    case 2: // extended segment address record
        if (length != 2)
            return parse_error(ctx);
        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 parse_error(ctx);
        ctx->base_offset = (uint32_t)parse_hex_short(ctx) << 16;
        break;
    case 5: // start linear address record
        break;

    default:
        return parse_error(ctx);
    }

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

    if (ctx->error)
        return parse_error(ctx);
    if (*ctx->ptr != '\r' && *ctx->ptr != '\n' && *ctx->ptr)
        return parse_error(ctx);
    if (((ctx->sum & 0xFF) + (checksum & 0xFF)) & 0xFF)
        return parse_error(ctx);

    // Return 1 for EOF records, to end the parsing
    return type == 1;
}
Example #2
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;
}