Source file: /~heha/hs/bl/msp430-usbbsl.zip/src/fileio.h

#include <windows.h>
#include <stdio.h>

#if defined(UNICODE) && !defined(_UNICODE)
# define _UNICODE
#endif
#include <tchar.h>

#define elemof(x) (sizeof(x)/sizeof(*(x)))
#define nobreak
#define T(x) TEXT(x)
typedef const TCHAR *PCTSTR;

// error codes
enum{
 IHEX_LINE_NO_COLON=-47,
 IHEX_LINE_TOO_SHORT,
 IHEX_LINE_GARBAGE,
 IHEX_WRONG_CHECKSUM,
 SREC_LINE_NO_S,
 SREC_LINE_TOO_SHORT,
 SREC_LINE_GARBAGE,
 SREC_WRONG_CHECKSUM,
 TEXT_LINE_GARBAGE,
};

// when writing HEX or SREC files
#define MAX_WRITE_BYTES_PER_LINE 16	// 32 bytes per line can be read, but this program writes shorter lines
#define MAX_CHAR_PER_LINE 82		// longest IHEX oder SREC record text line expected, including "\r\n\0"

struct LINEFILE{
 virtual int put(char*)=0;
 virtual int get(const char*)=0;
 virtual int putf(FILE*);
 virtual int getf(FILE*);
};

#pragma pack(1)
struct IHEXRECORD:LINEFILE{
 union{
  BYTE all[37];
  DWORD head;		// Combined access to the first 4 bytes
  struct{
   BYTE len;		// 0..20h, for the data part
   WORD addr;		// only for 16 bit address space, big endian!
   BYTE rectype;	// see below
   BYTE data[32];	// variable length, therefore checksum is not really at <cs> position
   BYTE cs;		// checksum, all bytes added must result in 0
  };
 };
 virtual int put(char*);	// encode record to ASCII
 virtual int get(const char*);	// decode record from ASCII
};
#pragma pack()
// record types [Wikipedia]
// 00 = data, len = 1..32, addr = load address
// 01 = end of file, len = 0, addr = start address
// 02 = segment address (x86), len = 2, addr = 0, data = segment address, endianness?
// 03 = FAR start address (x86), len = 4, addr = 0, data = CShi CSlo IPhi IPlo
// 04 = linear high address, len = 2, addr = 0, data = high part of data load address
// 05 = start linear address, len = 4, addr = 0, data = address (big endian?)


struct SRECRECORD:LINEFILE{
 union{
  BYTE all[39];
  DWORD head;		// Combined access to the first 4 bytes
  struct{
   BYTE rectype;	// see below, the 'S' is tought stripped to '0'
   BYTE len;		// byte count that follow, inclusive checksum
   BYTE data[36];	// contains a 2/3/4 byte address, variable length
   BYTE cs;		// checksum, from <len> bytes added must result in 0
  };
 };
 virtual int put(char*);	// encode record to ASCII
 virtual int get(const char*);	// decode record from ASCII
};
// record types [Wikipedia]
// 0 = Block Header, len = 3..37, addr = 2 Bytes (meist 0000h), data = vendor specific
// 1 = Data with 2-byte address, MSB first
// 2 = Data with 3-byte address
// 3 = Data with 4-byte address
// 5 = Record count, len = 3, addr = 2 Bytes
// 7 = End of block with 4-byte start address, len = 5
// 8 = End of block with 3-byte start address, len = 4
// 9 = End of block with 2-byte start address, len = 3


struct TEXTRECORD:LINEFILE{
 int len;			// 0..32 = data, '@' = address (always DWORD)
 union{
  DWORD addr;
  BYTE data[32];
 };
 virtual int put(char*);	// encode record to ASCII
 virtual int get(const char*);	// decode record from ASCII
};

// Abstract base class, i.e. an interface.
// All classes should work on streams, i.e. do not use fseek()
// Negative return values indicate errors.
// Non-negative return values indicate read or written bytes.
struct FILEIO{
 DWORD addr;		// the address for the data to read/write
 DWORD start;		// start address (if given)
 bool write;		// =true when in write mode
 bool havestart;	// start address found, or should be written
 virtual int Open(PCTSTR FileName,bool Write=false)=0;
 virtual int Read(BYTE*buf, int siz, DWORD&adr)=0;		// returns 0 on EOF; siz must be >0
 virtual int Write(const BYTE*buf, int siz, DWORD adr)=0;
 virtual int Close()=0;
};

// Derivated class for INTEL HEX files
class IHEXFILEIO:public FILEIO{
 FILE*f;		// stdio file handle (must be closed on error manually)
 IHEXRECORD hr;		// last interpreted record (to not seek backward)
 DWORD segaddr;		// address found in record type 2 (shiftet by 4), else 0
 DWORD linaddr;		// address found in record type 4 (shifted by 16), else 0
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr);
 virtual int Close();
};

// Derivated class for MOTOROLA SREC files
class SRECFILEIO:public FILEIO{
 FILE*f;		// stdio file handle (must be closed on error manually)
 SRECRECORD hr;		// last interpreted record (to not seek backward)
 BYTE addrlen;		// can be preset but can rise with address length on write (2, 3 or 4 is valid)
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr);
 virtual int Close();
};

// Derivated class for Texas Instrument's TEXT files
// (IMHO a useable file format but a stupid file extension)
class TEXTFILEIO:public FILEIO{
 FILE*f;		// stdio file handle
 TEXTRECORD hr;
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr);
 virtual int Close();
};

// Derivated class for ELF files (reading only)
class ELFFILEIO:public FILEIO{
 struct ELFHDR {
  union{
   struct{
    BYTE magic[4];	// "\x7FELF"
    BYTE eclass;	// 1 for 32-bit
    BYTE data;		// 1 for little endian, 2 for big endian
    BYTE version;	// (1)
    BYTE pad[9];		// (0xFF, then 0x00)
   };
   DWORD dw[4];
  }ident;
  WORD type;
  WORD machine;
  enum{
   T_EXEC	=  2,	// executable file
   M_MSP430	=105,
  };
  DWORD version;	// (1)
  DWORD entry;		// (00004400)	start address
  DWORD phoff;		// (00000034)	program header table
  DWORD shoff;		// (0000AF78)	section header table
  DWORD flags;		// (00000036)
  WORD ehsize;		// (0034)	this size
  WORD phentsize;	// (0020)	header table entry size (32 byte)
  WORD phnum;		// (0002)	header table entries (2)
  WORD shentsize;	// (0028)	section header entry size (40 byte)
  WORD shnum;		// (000D)	section header entries (13)
  WORD shstrndx;	// (000A)	index of section name string table (10)
 };
 struct Proghdr32 {
  DWORD	type,		// Headers with type != PT_LOAD (=1) are ignored
	offset,		// offset of data bits in ELF file
	vaddr,		// not needed (VMA)
	paddr,		// offset where to load into flash (LMA)
	filesz,		// size of section in file (0 for .bss)
	memsz,		// not needed
	flags,		// not needed
	align;		// not needed
 };
 BYTE*filemap;	// mapped file content
 int phti;	// current program header table to process
 int dataindex;	// current data byte index
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr) {return -1;}
 virtual int Close();
};

// Derivated class for binary dumps (with an address offset)
// Remember: DOS + CP/M .COM files had a fixed offset of 0x100
class BINFILEIO:public FILEIO{
 FILE*f;		// stdio file handle
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr);
 virtual int Close();
};

// Derivated class for given bytes on command line
class NOFILEIO:public FILEIO{
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr);
 virtual int Close();
};

// Derivated class for resource data (internal use for RAM bootloader)
class RESIO:public FILEIO{
 HRSRC hRes;	// loaded resource handle
 union {
  void*vp;
  BYTE*bp;
  DWORD*dp;
  long*lp;
 }pRes;		// moving pointer to mapped resource data
 long rest;	// number of data bytes not yet read
 virtual int Open(PCTSTR FileName,bool Write);
 virtual int Read(BYTE*buf, int siz, DWORD&adr);
 virtual int Write(const BYTE*buf, int siz, DWORD adr) {return -1;}
 virtual int Close();
};
// Each resource data chunk consists of:
// 1 DWORD target address
// 1 DWORD data length, in bytes
// n BYTE data
// The final record has a zero data length, its address is the start address,
// if not (DWORD)-1

Detected encoding: ASCII (7 bit)2