static int ihex_parse_single_record(ihex_rdata_t data, unsigned int length, ihex_record_t* record) { uint_t i; // Records needs to begin with record mark (usually ":") if (*(data) != IHEX_CHR_RECORDMARK) { IHEX_SET_ERROR_RETURN(IHEX_ERR_PARSE_ERROR, "Missing record mark"); } // Record layout: // 1 2 3 4 // 0 12 3456 78 90123456789012345678901234567890 12 // : 10 0100 00 214601360121470136007EFE09D21901 40 record->ihr_length = (ihex_rlen_t) length; record->ihr_address = (ihex_addr_t) ihex_fromhex16(data + 3); record->ihr_type = (ihex_rtype_t) ihex_fromhex8 (data + 7); record->ihr_checksum = (ihex_rchks_t) ihex_fromhex8 (data + 9 + record->ihr_length * 2); if ((record->ihr_data = (ihex_rdata_t) malloc(record->ihr_length)) == NULL) { IHEX_SET_ERROR_RETURN(IHEX_ERR_MALLOC_FAILED, "Could not allocate memory"); } // Records needs to end with CRLF or LF. if ( ( data[11 + record->ihr_length * 2] != 0x0D || data[12 + record->ihr_length * 2] != 0x0A) && (data[11 + record->ihr_length * 2] != 0x0A)) { free(record->ihr_data); IHEX_SET_ERROR_RETURN(IHEX_ERR_WRONG_RECORD_LENGTH, "Incorrect record length"); } for (i = 0; i < record->ihr_length; i ++) { if (data[9 + i*2] == 0x0A || data[9 + i*2] == 0x0D) { free(record->ihr_data); IHEX_SET_ERROR_RETURN(IHEX_ERR_WRONG_RECORD_LENGTH, "Unexpected end of line"); } record->ihr_data[i] = ihex_fromhex8(data + 9 + i*2); } if (ihex_check_record(record) != 0) { free(record->ihr_data); IHEX_SET_ERROR_RETURN(IHEX_ERR_INCORRECT_CHECKSUM, "Checksum validation failed"); } return 0; }
int ihex_rs_iterate_data(ihex_recordset_t* rs, uint_t *i, ihex_record_t **rec, uint32_t *off) { uint32_t offset; ihex_record_t *x; if (*i == 0 && off) { *off = 0x00; } for (; *i < rs->ihrs_count; ++(*i)) { x = (rs->ihrs_records + *i); if (rec) { *rec = x; //point the caller to current record } switch (x->ihr_type) { case IHEX_DATA: ++(*i); //proceed to next record in next call return 0; //let the caller process the data case IHEX_EOF: if (*i < rs->ihrs_count - 1) { IHEX_SET_ERROR_RETURN(IHEX_ERR_PREMATURE_EOF, "Premature EOF in record %i", *i + 1); } else { //FIXME signal end of records *i = 0; if (rec) { *rec = 0; } return 0; } case IHEX_ESA: offset = *(x->ihr_data) << 4; if (off) { *off = offset; } #ifdef IHEX_DEBUG printf("Switched offset to 0x%08x.\n", offset); #endif break; case IHEX_ELA: offset = (x->ihr_data[0] << 24) + (x->ihr_data[1] << 16); if (off) { *off = offset; } #ifdef IHEX_DEBUG printf("Switched offset to 0x%08x.\n", offset); #endif break; case IHEX_SSA: case IHEX_SLA: //skip body; next break; default: IHEX_SET_ERROR_RETURN(IHEX_ERR_UNKNOWN_RECORD_TYPE, "Unknown record type in record %i: 0x%02x", *i+1, x->ihr_type); } } IHEX_SET_ERROR_RETURN(IHEX_ERR_NO_EOF, "Missing EOF record"); }