/**************************************************************************** * 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 #endif #include "./flashrecord_p.h" #include #include 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; }