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;
}
Beispiel #2
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");
}