Files
aqhomecontrol/aqhome/hexfile/flashrecord.c
2023-04-18 21:17:56 +02:00

227 lines
4.9 KiB
C

/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./flashrecord_p.h"
#include <gwenhywfar/debug.h>
#include <gwenhywfar/misc.h>
GWEN_LIST_FUNCTIONS(AQH_FLASHRECORD, AQH_FlashRecord)
const AQH_HEXFILERECORD *_sampleAdjacentHexfileRecords(AQH_FLASHRECORD *fr, const AQH_HEXFILERECORD *hrStart);
AQH_FLASHRECORD *AQH_FlashRecord_new()
{
AQH_FLASHRECORD *fr;
GWEN_NEW_OBJECT(AQH_FLASHRECORD, fr);
GWEN_LIST_INIT(AQH_FLASHRECORD, fr);
return fr;
}
void AQH_FlashRecord_free(AQH_FLASHRECORD *fr)
{
if (fr) {
GWEN_LIST_FINI(AQH_FLASHRECORD, fr);
if (fr->dataPointer)
free(fr->dataPointer);
fr->dataPointer=NULL;
GWEN_FREE_OBJECT(fr);
}
}
uint32_t AQH_FlashRecord_GetAddress(const AQH_FLASHRECORD *fr)
{
if (fr)
return fr->address;
return 0;
}
void AQH_FlashRecord_SetAddress(AQH_FLASHRECORD *fr, uint32_t a)
{
if (fr)
fr->address=a;
}
uint32_t AQH_FlashRecord_GetDataLength(const AQH_FLASHRECORD *fr)
{
if (fr)
return fr->dataLength;
return 0;
}
uint8_t *AQH_FlashRecord_GetDataPointer(const AQH_FLASHRECORD *fr)
{
if (fr)
return fr->dataPointer;
return NULL;
}
void AQH_FlashRecord_DirectlySetData(AQH_FLASHRECORD *fr, uint32_t dataLength, uint8_t *dataPtr)
{
if (fr->dataPointer)
free(fr->dataPointer);
fr->dataPointer=dataPtr;
fr->dataLength=dataLength;
}
void AQH_FlashRecord_CopyAndSetData(AQH_FLASHRECORD *fr, uint32_t dataLength, const uint8_t *dataPtr)
{
if (fr) {
if (fr->dataPointer)
free(fr->dataPointer);
if (dataLength) {
fr->dataPointer=(uint8_t*) malloc(dataLength);
if (fr->dataPointer) {
if (dataPtr)
memmove(fr->dataPointer, dataPtr, dataLength);
else
memset(fr->dataPointer, 0, dataLength);
}
else {
fr->dataPointer=NULL;
fr->dataLength=0;
}
}
else {
fr->dataPointer=NULL;
fr->dataLength=0;
}
}
}
AQH_FLASHRECORD_LIST *AQH_FlashRecord_fromHexfileRecords(const AQH_HEXFILERECORD_LIST *hexFileRecordList)
{
AQH_FLASHRECORD_LIST *flashRecordList;
const AQH_HEXFILERECORD *hr;
uint32_t currentOffset=0;
flashRecordList=AQH_FlashRecord_List_new();
hr=AQH_HexfileRecord_List_First(hexFileRecordList);
while(hr) {
uint8_t t;
t=AQH_HexfileRecord_GetRecordType(hr);
if (t==AQH_HEXFILERECORD_TYPE_DATA) {
AQH_FLASHRECORD *fr;
fr=AQH_FlashRecord_new();
AQH_FlashRecord_SetAddress(fr, currentOffset+AQH_HexfileRecord_GetAddress(hr));
hr=_sampleAdjacentHexfileRecords(fr, hr);
AQH_FlashRecord_List_Add(fr, flashRecordList);
}
else {
if (t==AQH_HEXFILERECORD_TYPE_EXTSEG) {
const uint8_t *ptr;
if (AQH_HexfileRecord_GetByteCount(hr)<2) {
DBG_ERROR(AQH_LOGDOMAIN, "Invalid EXTSEG record (02) in file (too few data bytes)");
AQH_FlashRecord_List_free(flashRecordList);
return NULL;
}
ptr=AQH_HexfileRecord_GetDataPointer(hr);
currentOffset=((ptr[1]<<8)+ptr[0])<<4;
}
else if (t==AQH_HEXFILERECORD_TYPE_EXTLINEARADDR) {
const uint8_t *ptr;
if (AQH_HexfileRecord_GetByteCount(hr)<2) {
DBG_ERROR(AQH_LOGDOMAIN, "Invalid EXTLINEARADDR record (04) in file (too few data bytes)");
AQH_FlashRecord_List_free(flashRecordList);
return NULL;
}
ptr=AQH_HexfileRecord_GetDataPointer(hr);
currentOffset=((ptr[1]<<8)+ptr[0])<<16;
}
else if (t==AQH_HEXFILERECORD_TYPE_EOF) {
break;
}
hr=AQH_HexfileRecord_List_Next(hr);
}
} /* while */
if (AQH_FlashRecord_List_GetCount(flashRecordList)<1) {
AQH_FlashRecord_List_free(flashRecordList);
return NULL;
}
return flashRecordList;
}
const AQH_HEXFILERECORD *_sampleAdjacentHexfileRecords(AQH_FLASHRECORD *fr, const AQH_HEXFILERECORD *hrStart)
{
const AQH_HEXFILERECORD *hrNext;
const AQH_HEXFILERECORD *hr;
uint32_t len=0;
hrNext=AQH_HexfileRecord_List_FindNonAdjacentDataRecord(hrStart);
/* sample number of contiguous bytes */
hr=hrStart;
while(hr && hr!=hrNext) {
len+=AQH_HexfileRecord_GetByteCount(hr);
hr=AQH_HexfileRecord_List_Next(hr);
}
if (len) {
uint8_t *ptr;
uint32_t offs=0;
ptr=(uint8_t*) malloc(len);
hr=hrStart;
while(hr && hr!=hrNext) {
memmove(ptr+offs, AQH_HexfileRecord_GetDataPointer(hr), AQH_HexfileRecord_GetByteCount(hr));
offs+=AQH_HexfileRecord_GetByteCount(hr);
hr=AQH_HexfileRecord_List_Next(hr);
}
AQH_FlashRecord_DirectlySetData(fr, len, ptr);
}
return hrNext;
}