diff --git a/.gitignore b/.gitignore index 130ccea..1d1ba6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ bit2txt -bit2txt.o +draw_fpga diff --git a/Makefile b/Makefile index b011a1a..221c6b2 100644 --- a/Makefile +++ b/Makefile @@ -10,15 +10,13 @@ # CFLAGS = -Wall -g -TARGETS = bit2txt +TARGETS = bit2txt draw_fpga OBJS = $(TARGETS:=.o) +LDLIBS = -lxml2 .PHONY: all clean all: $(TARGETS) -genex: $(OBJS) - $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS) - clean: rm -f $(OBJS) $(TARGETS) diff --git a/README b/README index 72a680e..b1fc5d1 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ -Design Goals +Design Principles -- small independent command line utilities +- small independent command line utilities, no GUI - plain C, no C++ - simple Makefiles - text-based file formats diff --git a/bit2txt.c b/bit2txt.c index 4f19f5a..03ca755 100644 --- a/bit2txt.c +++ b/bit2txt.c @@ -1,5 +1,5 @@ // -// Authors: Wolfgang Spraul +// Author: Wolfgang Spraul // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -177,10 +177,11 @@ void hexdump(int offset, const uint8_t* data, int len) { int i, j; if (len) { - printf("#D hexdump offset %xh, len %i\n", offset, len); + printf("#D hexdump offset %xh, len 0x%x (%i)\n", + offset, len, len); i = 0; while (i < len) { - printf("#D %04x: %02x", i, data[i]); + printf("#D %05x: %02x", i, data[i]); for (j = 1; (j < 8) && (i + j < len); j++) { if (i + j >= len) break; printf(" %02x", data[i+j]); @@ -447,6 +448,11 @@ int main(int argc, char** argv) u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); u16_off+=2; printf("T1 FLR %u\n", u16); + // There are 3 types of frames. Type0 (clb, ioi + // and special blocks), type1 (bram) and type2 + // (iob). The size of a type0 and type1 is + // fixed, only the size of a type2 (iob) is + // specified with the FLR register. continue; } if (packet_hdr_register == COR1) { @@ -614,6 +620,151 @@ int main(int argc, char** argv) printf("T1 MFWR\n"); continue; } + if (packet_hdr_register == CTL) { + if (packet_hdr_wordcount != 1) { + fprintf(stderr, "#E 0x%x=0x%x Unexpected CTL" + " wordcount %u.\n", u16_off, + u16, packet_hdr_wordcount); + goto fail; + } + u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); + u16_off+=2; + printf("T1 CTL"); + if (u16 & 0x0040) { + printf(" DECRYPT"); + u16 &= ~0x0040; + } + if (u16 & 0x0020) { + if (u16 & 0x0010) + printf(" SBITS=NO_RW"); + else + printf(" SBITS=NO_READ"); + u16 &= ~0x0030; + } else if (u16 & 0x0010) { + printf(" SBITS=ICAP_READ"); + u16 &= ~0x0010; + } + if (u16 & 0x0008) { + printf(" PERSIST"); + u16 &= ~0x0008; + } + if (u16 & 0x0004) { + printf(" USE_EFUSE_KEY"); + u16 &= ~0x0004; + } + if (u16 & 0x0002) { + printf(" CRC_EXTSTAT_DISABLE"); + u16 &= ~0x0002; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // bit0 is reserved as 1, and we have seen + // bit7 on as well. + if (u16 != 0x81) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0081, u16); + continue; + } + if (packet_hdr_register == MASK) { + if (packet_hdr_wordcount != 1) { + fprintf(stderr, "#E 0x%x=0x%x Unexpected MASK" + " wordcount %u.\n", u16_off, + u16, packet_hdr_wordcount); + goto fail; + } + u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); + u16_off+=2; + printf("T1 MASK"); + if (u16 & 0x0040) { + printf(" DECRYPT"); + u16 &= ~0x0040; + } + if ((u16 & 0x0030) == 0x0030) { + printf(" SECURITY"); + u16 &= ~0x0030; + } + if (u16 & 0x0008) { + printf(" PERSIST"); + u16 &= ~0x0008; + } + if (u16 & 0x0004) { + printf(" USE_EFUSE_KEY"); + u16 &= ~0x0004; + } + if (u16 & 0x0002) { + printf(" CRC_EXTSTAT_DISABLE"); + u16 &= ~0x0002; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // It seems bit7 and bit0 are always masked in. + if (u16 != 0x81) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0081, u16); + continue; + } + if (packet_hdr_register == PWRDN_REG) { + if (packet_hdr_wordcount != 1) { + fprintf(stderr, "#E 0x%x=0x%x Unexpected PWRDN_REG" + " wordcount %u.\n", u16_off, + u16, packet_hdr_wordcount); + goto fail; + } + u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); + u16_off+=2; + printf("T1 PWRDN_REG"); + if (u16 & 0x4000) { + printf(" EN_EYES"); + u16 &= ~0x4000; + } + if (u16 & 0x0020) { + printf(" FILTER_B"); + u16 &= ~0x0020; + } + if (u16 & 0x0010) { + printf(" EN_PGSR"); + u16 &= ~0x0010; + } + if (u16 & 0x0004) { + printf(" EN_PWRDN"); + u16 &= ~0x0004; + } + if (u16 & 0x0001) { + printf(" KEEP_SCLK"); + u16 &= ~0x0001; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // Reserved bits 13:6 should be 00100010 + // according to documentation. + if (u16 != 0x0880) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x0880, u16); + continue; + } + if (packet_hdr_register == HC_OPT_REG) { + if (packet_hdr_wordcount != 1) { + fprintf(stderr, "#E 0x%x=0x%x Unexpected HC_OPT_REG" + " wordcount %u.\n", u16_off, + u16, packet_hdr_wordcount); + goto fail; + } + u16 = __be16_to_cpu(*(uint16_t*)&bit_data[u16_off+2]); + u16_off+=2; + printf("T1 HC_OPT_REG"); + if (u16 & 0x0040) { + printf(" INIT_SKIP"); + u16 &= ~0x0040; + } + if (u16) + printf(" 0x%x", u16); + printf("\n"); + // Reserved bits 5:0 should be 011111 + // according to documentation. + if (u16 != 0x001F) + printf("#W Expected reserved 0x%x, got 0x%x.\n", 0x001F, u16); + continue; + } printf("#W T1 %s (%u words)", xc6_regs[packet_hdr_register].name, packet_hdr_wordcount); diff --git a/draw_fpga.c b/draw_fpga.c new file mode 100644 index 0000000..7d92199 --- /dev/null +++ b/draw_fpga.c @@ -0,0 +1,103 @@ +// +// Author: Wolfgang Spraul +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version +// 3 of the License, or (at your option) any later version. +// + +#include +#include +#include +#include + +#include +#include +#include +#include + +static const char* empty_svg = +{ + "\n" + "\n" + " \n" + " \n" + "\n" +}; + +int main(int argc, char** argv) +{ + xmlDocPtr doc = 0; + xmlXPathContextPtr xpathCtx = 0; + xmlXPathObjectPtr xpathObj = 0; + + // create or overwrite fpga.svg + { + FILE* f = fopen("fpga.svg", "w+"); + if (!f) { + fprintf(stderr, "Cannot create fpga.svg\n"); + goto fail; + } + fprintf(f, empty_svg); + fclose(f); + } + xmlInitParser(); + doc = xmlParseFile("fpga.svg"); + if (!doc) { + fprintf(stderr, "Unable to parse fpga.svg.\n"); + goto fail_xml; + } + xpathCtx = xmlXPathNewContext(doc); + if (!xpathCtx) { + fprintf(stderr, "Cannot create XPath context.\n"); + goto fail_xml; + } + xmlXPathRegisterNs(xpathCtx, BAD_CAST "svg", BAD_CAST "http://www.w3.org/2000/svg"); + xpathObj = xmlXPathEvalExpression(BAD_CAST "//svg:*[@id='root']", xpathCtx); + if (!xpathObj) { + fprintf(stderr, "Cannot evaluate root expression.\n"); + goto fail_xml; + } + if (!xpathObj->nodesetval) { + fprintf(stderr, "Cannot find root node.\n"); + goto fail_xml; + } + if (xpathObj->nodesetval->nodeNr != 1) { + fprintf(stderr, "Found %i root nodes.\n", xpathObj->nodesetval->nodeNr); + goto fail_xml; + } + + { + xmlNodePtr new_node; + int i; + + for (i = 0; i < 10; i++) { + new_node = xmlNewChild(xpathObj->nodesetval->nodeTab[0], 0 /* xmlNsPtr */, BAD_CAST "use", 0 /* content */); + xmlSetProp(new_node, BAD_CAST "xlink:href", BAD_CAST "lib.svg#square"); + xmlSetProp(new_node, BAD_CAST "x", xmlXPathCastNumberToString(50+i*50)); + xmlSetProp(new_node, BAD_CAST "y", BAD_CAST "50"); + } + } + + xmlSaveFile("fpga.svg", doc); + + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + xmlFreeDoc(doc); + xmlCleanupParser(); + return EXIT_SUCCESS; + +fail_xml: + if (xpathObj) xmlXPathFreeObject(xpathObj); + if (xpathCtx) xmlXPathFreeContext(xpathCtx); + if (doc) xmlFreeDoc(doc); + xmlCleanupParser(); +fail: + return EXIT_FAILURE; +} diff --git a/lib.svg b/lib.svg new file mode 100644 index 0000000..3df5c66 --- /dev/null +++ b/lib.svg @@ -0,0 +1,7 @@ + + + + + +