📄 d_loader.c
字号:
//
// Date init 14.12.2004
//
// Revision date $Date:: 17-05-06 8:36 $
//
// Filename $Workfile:: d_loader.c $
//
// Version $Revision:: 75 $
//
// Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/d_loader.c $
//
// Platform C
//
#include "stdconst.h"
#include "modules.h"
#include "m_sched.h"
#include "d_loader.h"
#include "d_loader.r"
#include <string.h>
#include <ctype.h>
#define FILEVERSION (0x00000106L)
#define MAX_FILES ((SECTORSIZE/4) - 1) /* Last file entry is used for file version*/
#define MAX_WRITE_BUFFERS 4
#define FLASHOFFSET (0x100000L)
#define IS_LOADER_ERR(LStatus) (((LStatus) & 0xFF00) != SUCCESS)
#define SECTORINDEXUSERFLASH ((STARTOFUSERFLASH & ~FLASHOFFSET)/256/32)
#define SECTORPOINTERUSERFLASH (((STARTOFUSERFLASH & ~FLASHOFFSET) - ((SECTORINDEXUSERFLASH * 32) * 256))/256)
typedef struct
{
const UBYTE *pFlash;
const UWORD *pSectorNo;
ULONG ReadLength;
ULONG DataLength;
ULONG FileDlPtr;
UBYTE SearchStr[FILENAME_SIZE];
UWORD FileIndex;
UWORD CheckSum;
UBYTE SearchType;
UBYTE Status;
UBYTE FileType;
UBYTE WriteBufNo;
}HANDLE;
typedef struct
{
ULONG Buf[SECTORSIZE/4];
UBYTE BufIndex;
UBYTE Status;
}WRITEBUF;
static HANDLE HandleTable[MAX_HANDLES];
static WRITEBUF WriteBuffer[MAX_WRITE_BUFFERS];
static ULONG SectorTable[NOOFSECTORS>>5];
static const ULONG *Files;
static FILEHEADER Header;
static ULONG FreeUserFlash;
static UWORD FreeSectors;
void dLoaderUpdateSectorTable(void);
UWORD dLoaderGetFreeHandle(void);
const UBYTE * dLoaderGetNextSectorPtr(UBYTE Handle);
ULONG dLoaderReturnFreeFlash(void);
UWORD dLoaderAllocateHeader(UWORD Handle, ULONG *FileStartAdr, FILEHEADER *pHeader, UWORD HeaderByteSize, UWORD CompleteFileSectorSize);
UWORD dLoaderFlashFileHeader(UWORD Handle, ULONG FileStartAdr, FILEHEADER *pHeader, UWORD HeaderByteSize);
UWORD dLoaderFindFirstSector(UBYTE Type, UWORD SectorCount, UWORD *pSector);
UWORD dLoaderAllocateWriteBuffer(UWORD Handle);
UWORD dLoaderSetFilePointer(UWORD Handle, ULONG BytePtr, const UBYTE **pData);
UWORD dLoaderGetSectorNumber(ULONG Adr);
void dLoaderCheckVersion(void);
UWORD dLoaderCheckHandle(UWORD Handle, UBYTE Operation);
ULONG dLoaderCalcFreeFileSpace(UWORD NosOfFreeSectors);
UWORD dLoaderCheckDownload(UBYTE *pName);
UWORD dLoaderAvailFileNo(void);
void dLoaderInit(void)
{
UWORD Tmp;
LOADERInit;
Files = (const ULONG*)STARTOFFILETABLE;
/* Clear handle table */
for (Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
{
HandleTable[Tmp].Status = FREE;
HandleTable[Tmp].WriteBufNo = FREEBUFNO;
}
/* Clear write buffers */
for (Tmp = 0; Tmp < MAX_WRITE_BUFFERS; Tmp++)
{
WriteBuffer[Tmp].Status = FREE;
}
dLoaderCheckVersion();
dLoaderUpdateSectorTable();
FreeUserFlash = dLoaderReturnFreeFlash();
}
UWORD dLoaderAvailFileNo(void)
{
UBYTE Tmp, Tmp2;
UWORD ReturnVal;
const ULONG* FlashPtr;
ReturnVal = NOMOREFILES;
Tmp2 = 0;
FlashPtr = Files;
for(Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
{
/* Check for files allready downloading except datafiles as the have entered their */
/* filepointer in the filepointer table at begin of download */
if ((DOWNLOADING == HandleTable[Tmp].Status) && (DATAFILE != HandleTable[Tmp].FileType))
{
Tmp2++;
}
}
if ((0xFFFFFFFF == FlashPtr[(MAX_FILES - 1) - Tmp2]) || (0 == FlashPtr[(MAX_FILES - 1) - Tmp2]))
{
ReturnVal = SUCCESS;
}
return(ReturnVal);
}
UWORD dLoaderInsertPtrTable(const UBYTE *pAdr, UWORD Handle)
{
UWORD TmpCnt;
UWORD Status;
ULONG SectorCopy[(SECTORSIZE/4)];
const ULONG* FlashPtr;
/* It is possible to add the file as checking for number of files */
/* is done when initiating the file download */
FlashPtr = Files;
memset(SectorCopy, 0, sizeof(SectorCopy));
TmpCnt = MAX_FILES - 1;
while(TmpCnt)
{
/* TmpCnt-- first because you want to copy from index 0 */
TmpCnt--;
SectorCopy[TmpCnt + 1] = FlashPtr[TmpCnt];
}
/* Copy the new file in position 0 */
SectorCopy[0] = (ULONG)pAdr;
/* Add the File version to the top of the file list */
SectorCopy[MAX_FILES] = FlashPtr[MAX_FILES];
dLoaderWritePage((ULONG)Files, SECTORSIZE, SectorCopy);
/* FileIndex in HandleTable should be incremented by one - new file index is 0 */
for (TmpCnt = 0; TmpCnt < MAX_HANDLES; TmpCnt++)
{
if (HandleTable[TmpCnt].Status != FREE)
{
(HandleTable[TmpCnt].FileIndex)++;
}
}
HandleTable[Handle].FileIndex = 0;
Status = SUCCESS | Handle;
return(Status);
}
UWORD dLoaderDeleteFilePtr(UWORD Handle)
{
UWORD ErrorCode;
UWORD LongCnt;
ULONG SectorCopy[(SECTORSIZE>>2)];
const ULONG *pFlash;
ErrorCode = SUCCESS;
if (0xFFFFFFFF != Files[HandleTable[Handle].FileIndex])
{
ErrorCode = dLoaderCheckFiles(Handle);
if (0x8000 > ErrorCode)
{
pFlash = Files;
for (LongCnt = 0; LongCnt < (HandleTable[Handle].FileIndex); LongCnt++, pFlash++)
{
SectorCopy[LongCnt] = *pFlash;
}
/* Skip the file that has to be deleted */
pFlash++;
for ( ; LongCnt < (MAX_FILES - 1); LongCnt++, pFlash++)
{
SectorCopy[LongCnt] = *pFlash;
}
/* The top file entry is now free */
SectorCopy[MAX_FILES - 1] = 0xFFFFFFFF;
/* Insert the file version */
SectorCopy[MAX_FILES] = *pFlash;
/* Write the sectortable back into flash */
dLoaderWritePage((ULONG)Files, SECTORSIZE,(ULONG*) &SectorCopy);
dLoaderUpdateSectorTable();
FreeUserFlash = dLoaderReturnFreeFlash();
/* Update the HandleTable[].FileIndex */
for (LongCnt = 0; LongCnt < MAX_HANDLES; LongCnt++)
{
if ((HandleTable[Handle].FileIndex <= HandleTable[LongCnt].FileIndex) && (FREE != HandleTable[LongCnt].Status))
{
(HandleTable[LongCnt].FileIndex)--;
}
}
}
}
else
{
ErrorCode = FILENOTFOUND;
}
return(ErrorCode | Handle);
}
void dLoaderDeleteAllFiles(void)
{
ULONG Tmp;
ULONG SectorBuf[SECTORSIZE/4];
/* Close all handles - all files is to be wiped out */
for (Tmp = 0; Tmp < MAX_HANDLES; Tmp++)
{
dLoaderCloseHandle(Tmp);
}
for (Tmp = ((STARTOFUSERFLASH-FLASHOFFSET)/SECTORSIZE); Tmp < (SIZEOFFLASH/SECTORSIZE); Tmp++)
{
dLoaderErasePage(Tmp<<SECTORSIZESHIFT);
}
/* Insert the file version */
memset(SectorBuf, 0xFF, SECTORSIZE);
SectorBuf[(SECTORSIZE/4) - 1] = FILEVERSION;
dLoaderWritePage(STARTOFFILETABLE, SECTORSIZE, SectorBuf);
/* Update all other parameters */
dLoaderUpdateSectorTable();
FreeUserFlash = dLoaderReturnFreeFlash();
}
void dLoaderUpdateSectorTable(void)
{
UWORD Tmp;
UWORD SectorNo;
const FILEHEADER *pFile;
ULONG FileStart;
Tmp = 0;
memset(SectorTable, 0, sizeof(SectorTable));
/* All file pointer are occupied as default */
while (Tmp < MAX_FILES)
{
SectorNo = dLoaderGetSectorNumber((ULONG)&Files[Tmp]);
SectorTable[SectorNo>>5] |= (0x1 << (SectorNo - ((SectorNo>>5)<<5)));
Tmp += (SECTORSIZE >> 2);
}
for (Tmp = 0; Tmp < MAX_FILES; Tmp++)
{
if ((0xFFFFFFFF != Files[Tmp]) && (0x00000000 != Files[Tmp]))
{
pFile = (const FILEHEADER *) Files[Tmp];
FileStart = pFile->FileStartAdr;
/* This is necessary if the start address is at the first address in an sector */
SectorNo = dLoaderGetSectorNumber((ULONG)pFile->FileStartAdr);
SectorTable[SectorNo>>5] |= (0x1 << (SectorNo - ((SectorNo>>5)<<5)));
/* This is necessary as the first sector (where the fileheader is) is not */
/* included in the sector table */
SectorNo = dLoaderGetSectorNumber((ULONG)Files[Tmp]);
SectorTable[SectorNo>>5] |= (0x1 << (SectorNo - ((SectorNo>>5)<<5)));
SectorNo = 0;
while(FileStart > ((ULONG)(&(pFile->FileSectorTable[SectorNo]))) && (NOOFSECTORS > pFile->FileSectorTable[SectorNo]))
{
SectorTable[(pFile->FileSectorTable[SectorNo])>>5] |= (0x1 << ((pFile->FileSectorTable[SectorNo]) - (((pFile->FileSectorTable[SectorNo])>>5)<<5)));
if (0 == ((ULONG)(&(pFile->FileSectorTable[SectorNo+1])) & (SECTORSIZE-1)))
{
SectorNo += (((pFile->FileSectorTable[SectorNo]) << SECTORSIZESHIFT) - ((ULONG)&(pFile->FileSectorTable[SectorNo]) & ~FLASHOFFSET)>>1);
}
else
{
SectorNo++;
}
}
}
}
}
UWORD dLoaderCreateFileHeader(ULONG FileSize, UBYTE *pName, UBYTE LinearState, UBYTE FileType)
{
UWORD HeaderByteSize;
ULONG FileStartAdr;
ULONG CompleteFileByteSize;
UWORD Handle;
UBYTE Name[FILENAME_SIZE];
ULONG FileLength;
ULONG DataLength;
UWORD ErrorCode;
UWORD CompleteSectorNo;
UWORD Tmp;
memset(&(Header.FileName), 0, sizeof(Header.FileName));
memset(&(Header.FileSectorTable), 0xFF, sizeof(Header.FileSectorTable));
ErrorCode = dLoaderFind(pName, Name, &FileLength, &DataLength, (UBYTE)BUSY);
Handle = ErrorCode & 0x00FF;
if (SUCCESS == (ErrorCode & 0xFF00))
{
ErrorCode |= FILEEXISTS;
}
if (FILENOTFOUND == (ErrorCode & 0xFF00))
{
/* Here check for the download buffers for a matching download */
/* in progress */
ErrorCode &= 0x00FF;
ErrorCode = dLoaderCheckDownload(pName);
if (0x8000 > ErrorCode)
{
/* Check for file overflow */
ErrorCode = dLoaderAvailFileNo();
if (0x8000 > ErrorCode)
{
ErrorCode = dLoaderAllocateWriteBuffer(Handle);
if (0x8000 > ErrorCode)
{
dLoaderCopyFileName((Header.FileName), pName);
HandleTable[Handle].pSectorNo = 0;
HandleTable[Handle].DataLength = FileSize; /* used for end of file detection */
Header.FileSize = FileSize; /* used to program into flash */
if (DATAFILE == FileType)
{
Header.DataSize = 0;
}
else
{
Header.DataSize = FileSize;
}
HandleTable[Handle].FileType = FileType | LinearState; /* if it is a datafile it can be stopped */
Header.FileType = FileType | LinearState; /* FileType included for future appending */
/* File body size calculation*/
CompleteFileByteSize = FileSize;
/* Add the the fixed header to the fixed size */
CompleteFileByteSize += HEADERFIXEDSIZE;
/* Find the number of sectors used by the fixed file size */
CompleteSectorNo = (CompleteFileByteSize - 1) >> SECTORSIZESHIFT;
/* Add the size taken by the sectortable */
CompleteFileByteSize += (CompleteSectorNo << 1);
/* Recalc the number of sectors - to see wether the sectortable has caused */
/* the sectornumber to encrease */
Tmp = ((CompleteFileByteSize - 1) >> SECTORSIZESHIFT);
/* Substract from the original sectors used - Tmp holds the encreased number*/
Tmp -= CompleteSectorNo;
if (Tmp)
{
/* The sectortable takes up more than one sector */
CompleteFileByteSize += Tmp << 1;
CompleteSectorNo += Tmp;
}
HeaderByteSize = CompleteFileByteSize - FileSize;
if (HeaderByteSize & 0x0003)
{
/* Header size is not a multiplum of 4 - now make it a mul 4 */
HeaderByteSize += (0x0004 - (HeaderByteSize & 0x0003));
}
if (FileSize <= FreeUserFlash)
{
/* Allocate file header */
Tmp = (((CompleteFileByteSize - 1) >> SECTORSIZESHIFT) + 1);
Handle = dLoaderAllocateHeader(Handle, &FileStartAdr, &Header, HeaderByteSize, Tmp);
if (Handle < 0x8000)
{
dLoaderFlashFileHeader(Handle, FileStartAdr, &Header, HeaderByteSize);
/* If this is a datafile then add the filepointer to the filepointer table */
/* now as the datafile do not need to have a special size to be valid */
if (DATAFILE & HandleTable[Handle].FileType)
{
ErrorCode = dLoaderInsertPtrTable((const UBYTE *)HandleTable[Handle].FileDlPtr, Handle);
}
FreeSectors -= Tmp;
FreeUserFlash = dLoaderCalcFreeFileSpace(FreeSectors);
HandleTable[Handle].Status = DOWNLOADING;
}
}
else
{
ErrorCode = NOSPACE;
}
}
}
}
}
return(ErrorCode | Handle);
}
UWORD dLoaderWriteData(UWORD Handle, UBYTE *pBuf, UWORD *pLen)
{
UWORD Tmp;
UBYTE *pSectorBuf;
Handle = dLoaderCheckHandle(Handle, DOWNLOADING);
if (0x8000 > Handle)
{
if (*pLen > HandleTable[Handle].DataLength)
{
/* Write request exceeds filesize - only flash up to filesize*/
*pLen = HandleTable[Handle].DataLength;
WriteBuffer[HandleTable[Handle].WriteBufNo].Status = DLERROR; /* save error untill close handle */
}
pSectorBuf = (UBYTE *)WriteBuffer[HandleTable[Handle].WriteBufNo].Buf;
for(Tmp = 0; Tmp < *pLen; Tmp++)
{
pSectorBuf[WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex] = pBuf[Tmp];
if ((WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex) >= (SECTORSIZE-1))
{
dLoaderWritePage(((ULONG)HandleTable[Handle].pFlash & ~(SECTORSIZE - 1)), SECTORSIZE, WriteBuffer[HandleTable[Handle].WriteBufNo].Buf);
WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex = 0;
HandleTable[Handle].pFlash = dLoaderGetNextSectorPtr(Handle);
memset(WriteBuffer[HandleTable[Handle].WriteBufNo].Buf, 0xFF, sizeof(WriteBuffer[0].Buf));
}
else
{
(WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex)++;
}
}
HandleTable[Handle].DataLength -= *pLen;
/* Check for correct end of file */
if (0 == HandleTable[Handle].DataLength)
{
if ((WriteBuffer[HandleTable[Handle].WriteBufNo].BufIndex) != 0)
{
/* write the last data into the file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -