#ifndef BITFILE_H
#define BITFILE_H

/*************************************************************************
*
* bitfile - a library for reading and writing Xilinx bitfiles
*
* Copyright (C) 2007 John Kasunich (jmkasunich at fastmail dot fm)
*
**************************************************************************

This program is free software; you can redistribute it and/or
modify it under the terms of version 2 of the GNU General
Public License as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 USA

THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR
ANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISE
TO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable of
harming persons must have provisions for completely removing power
from all motors, etc, before persons enter any danger area.  All
machinery must be designed to comply with local and national safety
codes, and the authors of this software can not, and do not, take
any responsibility for such compliance.

This code was written as part of the EMC HAL project.  For more
information, go to www.linuxcnc.org.

**************************************************************************

Info about Xilinx bitfiles:

The format consists of several variable length chunks, preceded by what
seems to be a constant header.

Some details about the header hint that it might actually be a variable
length and content field as well, but I haven't found any files that
had different content there (I googled up some nearly ten year old files,
and I also examined ones made with the latest toolset).  So these
functions treat that header as a constant, and report any header that
doesn't match the standard as "not a bitfile".  The code would allow
that rule to be relaxed if needed later.

After the header, each "chunk" consists of a one byte "tag", a two or
four byte length, and "length" bytes of data (the body).

In some chunks, the body is a zero terminated printable string.  In others
it is a blob of binary data.  The file format doesn't care.

Standard Xilinx files use 5 chunks: 'a' through 'd' are zero-terminated
strings with information about the file.  'e' is a large binary blob
with the actual bitstream in it.  Xilinx uses 2 byte lengths for chunks
'a' thru 'd', and 4 bytes for chunk 'e'.  This library allows other
chunks, and assume that all have 4 byte lengths, except 'a' thru 'd'.

This library allows additional chunks to be added to the file.

*************************************************************************/

struct bitfile_chunk {
    char tag;
    int len;
    unsigned char *body;
};

#define BITFILE_MAXCHUNKS 50
/* list of chunks that use 2 byte length values, all others are 4 byte */
#define BITFILE_SMALLCHUNKS "abcd"
#define BITFILE_HEADERLEN 13

struct bitfile {
    char *filename;
    unsigned char header[BITFILE_HEADERLEN];
    int num_chunks;
    struct bitfile_chunk chunks[BITFILE_MAXCHUNKS];
};

/************************************************************************/

/* 'bitfile_new' allocates a struct bitfile, initializes its header field
   with the defaule xilinx header, and initializes its chunks as empty.
   It returns a pointer to the resulting struct, or NULL on error.
*/
struct bitfile *bitfile_new(void);


/* 'bitfile_free' frees all memory associated with a struct bitfile,
   including the chunk bodies and the struct itself.  It assumes that
   the struct was create by a call to 'bitfile_new' or 'bitfile_read'.
*/
void bitfile_free(struct bitfile *bf);


/* 'bitfile_read' reads a bitfile from disk, parses the individual chunks,
   and stores them in a struct bitfile in memory.  The struct and the chunk
   bodies are malloc'ed, and can be conveniently freed by `bitfile_free`.
   It returns a pointer to the new struct bitfile, or NULL on error.
*/
struct bitfile *bitfile_read(char *fname);


/* 'bitfile_write' writes the contents of a caller supplied struct bitfile
   to a specified file in standard bitfile format.  It returns zero on
   success, or -1 on failure.  It will write the standard xilinx 'a'
   through 'e' chunks first, and in order, even if they are not that way
   in the structure, followed by any extra chunks in the order in which
   they are encounterd.  (This is to ensure compatibility with other 
   programs that read bitfiles - this library doesn't care about chunk
   ordering, but other programs might.)
*/
int bitfile_write(struct bitfile *bf, char *fname);


/* 'bitfile_add_chunk` adds a new chunk to a caller supplied struct bitfile.
   The data is copied into a newly allocated block of memory, so the original
   can be dynamic memory, static memory, or anything else.  Returns zero on
   success, or -1 on error.
*/
int bitfile_add_chunk(struct bitfile *bf, char tag, int len, unsigned char *data);


/* 'bitfile_find_chunk` searches a caller supplied struct bitfile for a
   chunk whose tag matches 'tag', and returns a pointer to that chunk, or
   NULL if no match is found.  If 'n' is zero, it will return the first
   matching chunk, if 'n' is 1 it will return the second, etc.  Note that
   normal bitfiles never have more than one chunk with any given tag, so
   'n' should usually be zero.
*/
struct bitfile_chunk *bitfile_find_chunk(struct bitfile *bf, char tag, int n);


/* 'bitfile_print_chunk' searches a caller supplied struct bitfile for a
   chunk whose tag matches 'tag', and prints the body of that chunk as a
   string, preceeded by a caller supplied title.  If no match is found
   it prints nothing.  This is handy for printing out the contents of
   the standard Xilinx 'a' through 'd' fields, but will print binary
   junk if invoked on the 'e' chunk (the actual bitstream), or any chunk
   not containing a zero-terminated printable string.
*/
void bitfile_print_chunk(struct bitfile *bf, char tag, char *title);


/* 'bitfile_validate_xilinx_info` verifies that the caller supplied
   struct bitfile contains the minimum chunks to be a valid Xilinx
   bitstream - 'a' through 'e'.  It returns 0 for a valid bitstream,
   and -1 if any required chunk is missing.
*/
int bitfile_validate_xilinx_info(struct bitfile *bf);


/* 'bitfile_print_xilinx_info` invokes `bitfile_print_chunk` to print
   the standard Xilinx 'a' through 'd' chunks (design name, targeted part,
   date, and time) in a easily readable format.  It also prints the
   length of the 'e' chunk (the bitstream).
*/
void bitfile_print_xilinx_info(struct bitfile *bf);

#endif /* BITFILE_H */
