227 lines
4.9 KiB
C
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|