ar7: add eva image generation (thanks Axel Gembe)
authorEugene Konev <ejka@imfi.kspu.ru>
Mon, 22 Oct 2007 14:20:02 +0000 (14:20 +0000)
committerEugene Konev <ejka@imfi.kspu.ru>
Mon, 22 Oct 2007 14:20:02 +0000 (14:20 +0000)
SVN-Revision: 9401

Makefile
src/lzma2eva.c [new file with mode: 0644]

index f458693564915248e2001ceb1b1893f234347359..6a0c223c580637c30739e4d79cb66d6ac4d730f8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ PKG_NAME := firmware-utils
 include $(INCLUDE_DIR)/host-build.mk
 
 define cc
-       $(CC) $(HOST_CFLAGS) -include endian.h -o $(PKG_BUILD_DIR)/bin/$(1) src/$(1).c
+       $(CC) $(HOST_CFLAGS) -include endian.h -o $(PKG_BUILD_DIR)/bin/$(1) src/$(1).c $(2)
 endef
 
 define Build/Compile
@@ -27,6 +27,7 @@ define Build/Compile
        $(call cc,mkmylofw)
        $(call cc,mkcsysimg)
        $(call cc,mkzynfw)
+       $(call cc,lzma2eva,-lz)
 endef
 
 define Build/Install
diff --git a/src/lzma2eva.c b/src/lzma2eva.c
new file mode 100644 (file)
index 0000000..0bc13fa
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+    lzma2eva - convert lzma-compressed file to AVM EVA bootloader format
+    Copyright (C) 2007  Enrik Berkhan <Enrik.Berkhan@inka.de>
+
+    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 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+*/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <zlib.h> /* crc32 */
+
+#define checksum_add32(csum, data) \
+  csum += ((uint8_t *)&data)[0]; \
+  csum += ((uint8_t *)&data)[1]; \
+  csum += ((uint8_t *)&data)[2]; \
+  csum += ((uint8_t *)&data)[3];
+
+void
+usage(void)
+{
+  fprintf(stderr, "usage: lzma2eva <loadadddr> <entry> <lzmafile> <evafile>\n");
+  exit(1);
+}
+
+void
+pexit(const char *msg)
+{
+  perror(msg);
+  exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+
+  const char *infile, *outfile;
+  FILE *in, *out;
+  static const uint8_t buf[4096];
+  size_t elems;
+
+  uint8_t properties;
+  uint32_t dictsize;
+  uint64_t datasize;
+
+  uint32_t magic = 0xfeed1281L;
+  uint32_t reclength = 0;
+  fpos_t reclengthpos;
+  uint32_t loadaddress = 0;
+  uint32_t type = 0x075a0201L; /* might be 7Z 2.1? */
+  uint32_t checksum = 0;
+
+  uint32_t compsize = 0;
+  fpos_t compsizepos;
+  uint32_t datasize32 = 0;
+  uint32_t datacrc32 = crc32(0, 0, 0);
+
+  uint32_t zero = 0;
+  uint32_t entry = 0;
+
+  if (argc != 5)
+    usage();
+
+  /* "parse" command line */
+  loadaddress = strtoul(argv[1], 0, 0);
+  entry = strtoul(argv[2], 0, 0);
+  infile = argv[3];
+  outfile = argv[4];
+
+  in = fopen(infile, "rb");
+  if (!in)
+    pexit("fopen");
+  out = fopen(outfile, "w+b");
+  if (!out)
+    pexit("fopen");
+
+  /* read LZMA header */
+  if (1 != fread(&properties, sizeof properties, 1, in))
+    pexit("fread");
+  if (1 != fread(&dictsize, sizeof dictsize, 1, in))
+    pexit("fread");
+  if (1 != fread(&datasize, sizeof datasize, 1, in))
+    pexit("fread");
+
+  /* write EVA header */
+  if (1 != fwrite(&magic, sizeof magic, 1, out))
+    pexit("fwrite");
+  if (fgetpos(out, &reclengthpos))
+    pexit("fgetpos");
+  if (1 != fwrite(&reclength, sizeof reclength, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&loadaddress, sizeof loadaddress, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&type, sizeof type, 1, out))
+    pexit("fwrite");
+
+  /* write EVA LZMA header */
+  if (fgetpos(out, &compsizepos))
+    pexit("fgetpos");
+  if (1 != fwrite(&compsize, sizeof compsize, 1, out))
+    pexit("fwrite");
+  /* XXX check length */
+  datasize32 = (uint32_t)datasize;
+  if (1 != fwrite(&datasize32, sizeof datasize32, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&datacrc32, sizeof datacrc32, 1, out))
+    pexit("fwrite");
+
+  /* write modified LZMA header */
+  if (1 != fwrite(&properties, sizeof properties, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&dictsize, sizeof dictsize, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&zero, 3, 1, out))
+    pexit("fwrite");
+
+  /* copy compressed data, calculate crc32 */
+  while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, in))) {
+    compsize += elems;
+    if (elems != fwrite(&buf, sizeof buf[0], elems, out))
+      pexit("fwrite");
+    datacrc32 = crc32(datacrc32, buf, elems);
+  }
+  if (ferror(in))
+    pexit("fread");
+  fclose(in);
+
+  /* re-write record length */
+  reclength = compsize + 24;
+  if (fsetpos(out, &reclengthpos))
+    pexit("fsetpos");
+  if (1 != fwrite(&reclength, sizeof reclength, 1, out))
+    pexit("fwrite");
+
+  /* re-write EVA LZMA header including size and data crc */
+  if (fsetpos(out, &compsizepos))
+    pexit("fsetpos");
+  if (1 != fwrite(&compsize, sizeof compsize, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&datasize32, sizeof datasize32, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&datacrc32, sizeof datacrc32, 1, out))
+    pexit("fwrite");
+
+  /* calculate record checksum */
+  checksum += reclength;
+  checksum += loadaddress;
+  checksum_add32(checksum, type);
+  checksum_add32(checksum, compsize);
+  checksum_add32(checksum, datasize32);
+  checksum_add32(checksum, datacrc32);
+  if (fseek(out, 0, SEEK_CUR))
+    pexit("fseek");
+  while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, out))) {
+    size_t i;
+    for (i = 0; i < elems; ++i)
+      checksum += buf[i];
+  }
+  if (ferror(out))
+    pexit("fread");
+  if (fseek(out, 0, SEEK_CUR))
+    pexit("fseek");
+
+  checksum = ~checksum + 1;
+  if (1 != fwrite(&checksum, sizeof checksum, 1, out))
+    pexit("fwrite");
+
+  /* write entry record */
+  if (1 != fwrite(&zero, sizeof zero, 1, out))
+    pexit("fwrite");
+  if (1 != fwrite(&entry, sizeof entry, 1, out))
+    pexit("fwrite");
+
+  if (fclose(out))
+    pexit("fclose");
+
+  return 0;
+}