aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJames <>2015-11-04 11:49:21 +0000
committerJames <>2015-11-04 11:49:21 +0000
commit716ca530e1c4515d8683c9d5be3d56b301758b66 (patch)
tree700eb5bcc1a462a5f21dcec15ce7c97ecfefa772 /tools
downloadtrunk-47381-716ca530e1c4515d8683c9d5be3d56b301758b66.tar.gz
trunk-47381-716ca530e1c4515d8683c9d5be3d56b301758b66.tar.bz2
trunk-47381-716ca530e1c4515d8683c9d5be3d56b301758b66.zip
trunk-47381HEADmaster
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile125
-rw-r--r--tools/autoconf/Makefile37
-rw-r--r--tools/autoconf/patches/000-relocatable.patch229
-rw-r--r--tools/autoconf/patches/001-no_emacs_lib.patch22
-rw-r--r--tools/autoconf/patches/002-musl_host_fixup.patch24
-rw-r--r--tools/automake/Makefile50
-rwxr-xr-xtools/automake/files/aclocal2
-rw-r--r--tools/automake/patches/000-relocatable.patch96
-rw-r--r--tools/automake/patches/100-aclocal-skip-not-existing-directories.patch15
-rw-r--r--tools/automake/patches/200-do-not-override-silent-rules.patch13
-rw-r--r--tools/b43-tools/Makefile51
-rwxr-xr-xtools/b43-tools/files/b43-fwsquash.py149
-rw-r--r--tools/b43-tools/patches/001-fw-dirname.patch16
-rw-r--r--tools/b43-tools/patches/002-no_libfl.patch14
-rw-r--r--tools/bc/Makefile21
-rw-r--r--tools/bc/patches/001-no_doc.patch23
-rw-r--r--tools/bison/Makefile30
-rw-r--r--tools/bison/patches/010-intl-stub-compat.patch15
-rw-r--r--tools/bison/patches/100-fix-gets-removal.patch16
-rwxr-xr-xtools/bison/scripts/yacc2
-rw-r--r--tools/ccache/Makefile35
-rwxr-xr-xtools/ccache/files/ccache_cc2
-rwxr-xr-xtools/ccache/files/ccache_cxx2
-rw-r--r--tools/ccache/patches/100-honour-copts.patch33
-rw-r--r--tools/cloog/Makefile41
-rw-r--r--tools/cmake/Makefile28
-rw-r--r--tools/cmake/patches/100-disable_qt_tests.patch31
-rw-r--r--tools/cmake/patches/110-freebsd-compat.patch42
-rw-r--r--tools/dosfstools/Makefile38
-rw-r--r--tools/dosfstools/patches/0001-Add-tags-and-editor-backup-files-to-.gitignore.patch25
-rw-r--r--tools/dosfstools/patches/0002-Fix-indentation-of-fix-power-loss-damage-commit.patch100
-rw-r--r--tools/dosfstools/patches/0003-mkfs.fat.c-Use-unsigned-char-for-binary-data.patch33
-rw-r--r--tools/dosfstools/patches/0004-Make-all-char-that-may-take-literals-const.patch169
-rw-r--r--tools/dosfstools/patches/0005-mkfs.fat-Allow-0xF0-to-be-specified-as-media-byte.patch122
-rw-r--r--tools/dosfstools/patches/0006-fsck.fat-Make-r-option-default.patch603
-rw-r--r--tools/dosfstools/patches/0007-Makefile-fix-typo-in-uninstall-man.patch30
-rw-r--r--tools/dosfstools/patches/0008-Makefile-avoid-using-install-D.patch43
-rw-r--r--tools/dosfstools/patches/0009-Improve-.gitignore.patch28
-rw-r--r--tools/dosfstools/patches/0010-Remove-non-standard-int-types.patch538
-rw-r--r--tools/dosfstools/patches/0011-Remove-linux-msdos_fs.h-includes.patch209
-rw-r--r--tools/dosfstools/patches/0012-fsck.fat-Fix-read-beyond-end-of-array-on-FAT12.patch54
-rw-r--r--tools/dosfstools/patches/0013-Add-compatible-ioctl-calls-for-OSX-and-FreeBSD.patch217
-rw-r--r--tools/dosfstools/patches/0014-Add-OSX-and-FreeBSD-support.patch334
-rw-r--r--tools/e2fsprogs/Makefile51
-rw-r--r--tools/e2fsprogs/patches/001-exit_0_on_corrected_errors.patch11
-rw-r--r--tools/e2fsprogs/patches/002-dont-build-e4defrag.patch11
-rw-r--r--tools/e2fsprogs/patches/003-openbsd-compat.patch24
-rw-r--r--tools/e2fsprogs/patches/004-freebsd-compat.patch13
-rw-r--r--tools/e2fsprogs/patches/005-darwin-compat.patch22
-rw-r--r--tools/elftosb/Makefile26
-rw-r--r--tools/elftosb/patches/001-libm.patch11
-rw-r--r--tools/elftosb/patches/002-fix-header-path.patch19
-rw-r--r--tools/elftosb/patches/003-use-ldflags.patch26
-rw-r--r--tools/expat/Makefile25
-rw-r--r--tools/findutils/Makefile20
-rw-r--r--tools/findutils/patches/21-Fix-time_t-vs-long-int-mismatches.patch158
-rw-r--r--tools/firmware-utils/Makefile82
-rw-r--r--tools/firmware-utils/src/add_header.c138
-rw-r--r--tools/firmware-utils/src/addpattern.c333
-rw-r--r--tools/firmware-utils/src/airlink.c332
-rw-r--r--tools/firmware-utils/src/asustrx.c256
-rw-r--r--tools/firmware-utils/src/bcm_tag.h70
-rw-r--r--tools/firmware-utils/src/bcmalgo.c248
-rw-r--r--tools/firmware-utils/src/bcmalgo.h83
-rw-r--r--tools/firmware-utils/src/buffalo-enc.c304
-rw-r--r--tools/firmware-utils/src/buffalo-lib.c480
-rw-r--r--tools/firmware-utils/src/buffalo-lib.h121
-rw-r--r--tools/firmware-utils/src/buffalo-tag.c374
-rw-r--r--tools/firmware-utils/src/buffalo-tftp.c177
-rw-r--r--tools/firmware-utils/src/csysimg.h79
-rw-r--r--tools/firmware-utils/src/cyg_crc.h109
-rw-r--r--tools/firmware-utils/src/cyg_crc16.c110
-rw-r--r--tools/firmware-utils/src/cyg_crc32.c172
-rw-r--r--tools/firmware-utils/src/dgfirmware.c376
-rw-r--r--tools/firmware-utils/src/dgn3500sum.c167
-rw-r--r--tools/firmware-utils/src/edimax_fw_header.c386
-rw-r--r--tools/firmware-utils/src/encode_crc.c151
-rw-r--r--tools/firmware-utils/src/fix-u-media-header.c354
-rw-r--r--tools/firmware-utils/src/fw.h70
-rw-r--r--tools/firmware-utils/src/hcsmakeimage.c181
-rw-r--r--tools/firmware-utils/src/imagetag.c492
-rw-r--r--tools/firmware-utils/src/imagetag.ggo46
-rw-r--r--tools/firmware-utils/src/imagetag_cmdline.c1193
-rw-r--r--tools/firmware-utils/src/imagetag_cmdline.h275
-rw-r--r--tools/firmware-utils/src/lzma2eva.c190
-rw-r--r--tools/firmware-utils/src/makeamitbin.c316
-rw-r--r--tools/firmware-utils/src/md5.c307
-rw-r--r--tools/firmware-utils/src/md5.h65
-rw-r--r--tools/firmware-utils/src/mkbrncmdline.c168
-rw-r--r--tools/firmware-utils/src/mkbrnimg.c189
-rw-r--r--tools/firmware-utils/src/mkcameofw.c433
-rw-r--r--tools/firmware-utils/src/mkcasfw.c1030
-rw-r--r--tools/firmware-utils/src/mkchkimg.c327
-rw-r--r--tools/firmware-utils/src/mkcsysimg.c1157
-rw-r--r--tools/firmware-utils/src/mkdapimg.c226
-rw-r--r--tools/firmware-utils/src/mkdcs932.c39
-rw-r--r--tools/firmware-utils/src/mkdniimg.c208
-rw-r--r--tools/firmware-utils/src/mkedimaximg.c259
-rw-r--r--tools/firmware-utils/src/mkfwimage.c467
-rw-r--r--tools/firmware-utils/src/mkfwimage2.c447
-rw-r--r--tools/firmware-utils/src/mkheader_gemtek.c211
-rw-r--r--tools/firmware-utils/src/mkhilinkfw.c322
-rw-r--r--tools/firmware-utils/src/mkmylofw.c1297
-rw-r--r--tools/firmware-utils/src/mkplanexfw.c269
-rw-r--r--tools/firmware-utils/src/mkporayfw.c791
-rw-r--r--tools/firmware-utils/src/mkrtn56uimg.c294
-rw-r--r--tools/firmware-utils/src/mksenaofw.c417
-rw-r--r--tools/firmware-utils/src/mktitanimg.c1040
-rw-r--r--tools/firmware-utils/src/mktitanimg.h171
-rw-r--r--tools/firmware-utils/src/mktplinkfw.c1222
-rw-r--r--tools/firmware-utils/src/mktplinkfw2.c982
-rw-r--r--tools/firmware-utils/src/mkwrgimg.c240
-rw-r--r--tools/firmware-utils/src/mkzcfw.c408
-rw-r--r--tools/firmware-utils/src/mkzynfw.c1131
-rw-r--r--tools/firmware-utils/src/motorola-bin.c227
-rw-r--r--tools/firmware-utils/src/myloader.h176
-rw-r--r--tools/firmware-utils/src/nand_ecc.c204
-rw-r--r--tools/firmware-utils/src/osbridge-crc.c309
-rw-r--r--tools/firmware-utils/src/pc1crypt.c361
-rw-r--r--tools/firmware-utils/src/ptgen.c246
-rw-r--r--tools/firmware-utils/src/seama.c529
-rw-r--r--tools/firmware-utils/src/seama.h108
-rw-r--r--tools/firmware-utils/src/sha1.c443
-rw-r--r--tools/firmware-utils/src/sha1.h57
-rw-r--r--tools/firmware-utils/src/spw303v.c242
-rw-r--r--tools/firmware-utils/src/srec2bin.c524
-rw-r--r--tools/firmware-utils/src/tplink-safeloader.c559
-rw-r--r--tools/firmware-utils/src/trx.c418
-rw-r--r--tools/firmware-utils/src/trx2edips.c171
-rw-r--r--tools/firmware-utils/src/trx2usr.c186
-rw-r--r--tools/firmware-utils/src/wrt400n.c334
-rw-r--r--tools/firmware-utils/src/xorimage.c135
-rw-r--r--tools/firmware-utils/src/zynos.h225
-rw-r--r--tools/firmware-utils/src/zyxbcm.c259
-rw-r--r--tools/flex/Makefile28
-rw-r--r--tools/flex/patches/100-remove_no_undefined.patch18
-rw-r--r--tools/flock/Makefile22
-rw-r--r--tools/flock/src/flock.c325
-rw-r--r--tools/gengetopt/Makefile30
-rw-r--r--tools/gengetopt/patches/100-dependency_fix.patch11
-rw-r--r--tools/gengetopt/patches/200-no_docs_tests.patch13
-rw-r--r--tools/gmp/Makefile35
-rw-r--r--tools/include/byteswap.h5
-rw-r--r--tools/include/elf.h3007
-rw-r--r--tools/include/endian.h40
-rw-r--r--tools/include/getline.h72
-rw-r--r--tools/include/sys/sysmacros.h56
-rw-r--r--tools/libelf/Makefile51
-rw-r--r--tools/libtool/Makefile41
-rw-r--r--tools/libtool/files/libtool-v1.5.patch118
-rw-r--r--tools/libtool/files/libtool-v2.2.patch123
-rw-r--r--tools/libtool/files/libtool-v2.4.patch160
-rw-r--r--tools/libtool/patches/000-relocatable.patch141
-rw-r--r--tools/libtool/patches/001-fix-func_append.patch22
-rw-r--r--tools/libtool/patches/100-libdir-fixes.patch94
-rw-r--r--tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch20
-rw-r--r--tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch24
-rw-r--r--tools/libtool/patches/150-trailingslash.patch49
-rw-r--r--tools/libtool/patches/160-passthrough-ssp.patch12
-rw-r--r--tools/libtool/patches/200-openwrt-branding.patch112
-rw-r--r--tools/lzma-old/Makefile36
-rw-r--r--tools/lzma-old/patches/100-lzma_zlib.patch404
-rw-r--r--tools/lzma-old/patches/110-ranlib.patch10
-rw-r--r--tools/lzma/Makefile36
-rw-r--r--tools/lzma/patches/001-large_files.patch13
-rw-r--r--tools/lzma/patches/002-lzmp.patch1059
-rw-r--r--tools/lzma/patches/003-compile_fixes.patch26
-rw-r--r--tools/lzma/patches/100-static_library.patch70
-rw-r--r--tools/m4/Makefile28
-rw-r--r--tools/m4/patches/100-fix-gets-removal.patch17
-rw-r--r--tools/make-ext4fs/Makefile40
-rw-r--r--tools/missing-macros/Makefile28
-rw-r--r--tools/missing-macros/src/README100
-rwxr-xr-xtools/missing-macros/src/bin/help2man29
-rwxr-xr-xtools/missing-macros/src/bin/makeinfo112
-rw-r--r--tools/missing-macros/src/m4/as-ac-expand.m443
-rw-r--r--tools/missing-macros/src/m4/as-compiler-flag.m462
-rw-r--r--tools/missing-macros/src/m4/as-unaligned-access.m441
-rw-r--r--tools/missing-macros/src/m4/as-version.m471
-rw-r--r--tools/missing-macros/src/m4/dnet.m4322
-rw-r--r--tools/missing-macros/src/m4/fake-gtk-doc-check.m413
-rw-r--r--tools/missing-macros/src/m4/fake-intltool.m416
-rw-r--r--tools/missing-macros/src/m4/glibc2.m430
-rw-r--r--tools/missing-macros/src/m4/glibc21.m430
-rw-r--r--tools/missing-macros/src/m4/intdiv0.m484
-rw-r--r--tools/missing-macros/src/m4/intmax.m433
-rw-r--r--tools/missing-macros/src/m4/inttypes-pri.m436
-rw-r--r--tools/missing-macros/src/m4/inttypes_h.m426
-rw-r--r--tools/missing-macros/src/m4/lib-ld.m4110
-rw-r--r--tools/missing-macros/src/m4/lib-link.m4774
-rw-r--r--tools/missing-macros/src/m4/lib-prefix.m4224
-rw-r--r--tools/missing-macros/src/m4/mfx_acc.m4163
-rw-r--r--tools/missing-macros/src/m4/mfx_cppflags.m441
-rw-r--r--tools/missing-macros/src/m4/mfx_limits.m4154
-rw-r--r--tools/missing-macros/src/m4/progtest.m492
-rw-r--r--tools/missing-macros/src/m4/stdint_h.m426
-rw-r--r--tools/missing-macros/src/m4/uintmax_t.m430
-rw-r--r--tools/missing-macros/src/m4/va_copy.m4111
-rw-r--r--tools/missing-macros/src/m4/wint_t.m428
-rw-r--r--tools/mkimage/Makefile46
-rw-r--r--tools/mkimage/patches/010-freebsd-ulong-fix.patch13
-rw-r--r--tools/mkimage/patches/020-include_compile_fix.patch10
-rw-r--r--tools/mkimage/patches/030-allow-to-use-different-magic.patch63
-rw-r--r--tools/mkimage/patches/040-include_order.patch11
-rw-r--r--tools/mkimage/patches/050-image_h_portability.patch31
-rw-r--r--tools/mkimage/patches/060-remove_kernel_includes.patch35
-rw-r--r--tools/mkimage/patches/070-socfpgaimage_portability.patch52
-rw-r--r--tools/mkimage/patches/080-remove_compiler_check.patch16
-rw-r--r--tools/mkimage/patches/100-freebsd-compat.patch14
-rw-r--r--tools/mkimage/patches/200-gcc5_compat.patch93
-rw-r--r--tools/mklibs/Makefile34
-rw-r--r--tools/mklibs/include/elf.h2559
-rw-r--r--tools/mklibs/patches/001-compile.patch8
-rw-r--r--tools/mklibs/patches/002-disable_symbol_checks.patch20
-rw-r--r--tools/mklibs/patches/003-no_copy.patch50
-rw-r--r--tools/mklibs/patches/004-libpthread_link.patch28
-rw-r--r--tools/mklibs/patches/005-duplicate_syms.patch35
-rw-r--r--tools/mklibs/patches/006-uclibc_init.patch14
-rw-r--r--tools/mklibs/patches/007-gc_sections.patch11
-rw-r--r--tools/mklibs/patches/008-uclibc_libgcc_link.patch37
-rw-r--r--tools/mklibs/patches/009-uclibc_libpthread_symbols.patch63
-rw-r--r--tools/mklibs/patches/010-remove_STT_GNU_IFUNC.patch20
-rw-r--r--tools/mklibs/patches/011-remove_multiarch.patch10
-rw-r--r--tools/mm-macros/Makefile31
-rw-r--r--tools/mpc/Makefile28
-rw-r--r--tools/mpfr/Makefile27
-rw-r--r--tools/mpfr/patches/001-only_src.patch22
-rw-r--r--tools/mpfr/patches/100-freebsd-compat.patch10
-rw-r--r--tools/mtd-utils/Makefile60
-rw-r--r--tools/mtd-utils/include/fls.h2
-rw-r--r--tools/mtd-utils/include/linux/types.h18
-rw-r--r--tools/mtd-utils/patches/100-sscanf_fix.patch11
-rw-r--r--tools/mtd-utils/patches/110-portability.patch191
-rw-r--r--tools/mtd-utils/patches/130-lzma_jffs2.patch5030
-rw-r--r--tools/mtd-utils/patches/134-freebsd_loff_t.patch14
-rw-r--r--tools/mtd-utils/patches/135-mkubifs_optional_lzo.patch119
-rw-r--r--tools/mtd-utils/patches/136-mkfs.ubifs-xz-support.patch378
-rw-r--r--tools/mtd-utils/patches/137-no_extern_inline.patch41
-rw-r--r--tools/mtd-utils/patches/200-libubigen-add-ubigen_write_terminator-function.patch89
-rw-r--r--tools/mtd-utils/patches/201-ubinize-add-terminator-support.patch77
-rw-r--r--tools/mtd-utils/patches/300-libfec_use_standard_unsigned_long.patch35
-rw-r--r--tools/mtd-utils/patches/310-add-static-linking-option.patch43
-rw-r--r--tools/mtools/Makefile38
-rw-r--r--tools/mtools/patches/100-compile_fix.patch19
-rw-r--r--tools/padjffs2/Makefile36
-rw-r--r--tools/padjffs2/src/Makefile15
-rw-r--r--tools/padjffs2/src/padjffs2.c198
-rw-r--r--tools/patch-image/Makefile28
-rw-r--r--tools/patch-image/src/patch-cmdline.c79
-rw-r--r--tools/patch-image/src/patch-dtb.c101
-rw-r--r--tools/patch/Makefile23
-rw-r--r--tools/patchelf/Makefile26
-rw-r--r--tools/patchelf/patches/100-portability.patch8
-rw-r--r--tools/pkg-config/Makefile39
-rwxr-xr-xtools/pkg-config/files/pkg-config3
-rw-r--r--tools/ppl/Makefile37
-rw-r--r--tools/ppl/patches/001-disable-serial-tests.patch44
-rw-r--r--tools/qemu/Makefile40
-rw-r--r--tools/quilt/Makefile36
-rw-r--r--tools/quilt/patches/000-relocatable.patch170
-rw-r--r--tools/quilt/patches/001-fix_compile.patch18
-rw-r--r--tools/scons/Makefile35
-rwxr-xr-xtools/scons/files/pywrap.sh15
-rw-r--r--tools/scons/patches/001-platform_env.patch11
-rw-r--r--tools/sdimage/Makefile37
-rw-r--r--tools/sed/Makefile43
-rw-r--r--tools/sed/patches/001-musl_host_fixup.patch24
-rw-r--r--tools/sparse/Makefile22
-rw-r--r--tools/squashfs/Makefile39
-rw-r--r--tools/squashfs/patches/100-lzma.patch22
-rw-r--r--tools/squashfs/patches/110-no_nonstatic_inline.patch11
-rw-r--r--tools/squashfs4/Makefile42
-rw-r--r--tools/squashfs4/patches/100-portability.patch40
-rw-r--r--tools/squashfs4/patches/110-allow_static_liblzma.patch30
-rw-r--r--tools/squashfs4/patches/120-cygwin_fixes.patch153
-rw-r--r--tools/squashfs4/patches/150-freebsd_fixes.patch10
-rw-r--r--tools/squashfs4/patches/160-expose_lzma_xz_options.patch929
-rw-r--r--tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch72
-rw-r--r--tools/squashfs4/patches/180-openbsd_compat.patch26
-rw-r--r--tools/squashfs4/patches/190-no_nonstatic_inline.patch36
-rw-r--r--tools/sstrip/Makefile25
-rw-r--r--tools/sstrip/src/sstrip.c465
-rw-r--r--tools/tar/Makefile30
-rw-r--r--tools/tar/patches/100-fix_xattr_disable.patch17
-rw-r--r--tools/upslug2/Makefile35
-rw-r--r--tools/upslug2/patches/100-libpcap_fix.patch153
-rw-r--r--tools/upslug2/patches/110-wrt350nv2_support.patch279
-rw-r--r--tools/upx/Makefile36
-rw-r--r--tools/upx/patches/100-lzmaonly.patch156
-rw-r--r--tools/wrt350nv2-builder/Makefile41
-rw-r--r--tools/wrt350nv2-builder/src/crypt.h132
-rw-r--r--tools/wrt350nv2-builder/src/ioapi.c177
-rw-r--r--tools/wrt350nv2-builder/src/ioapi.h75
-rw-r--r--tools/wrt350nv2-builder/src/md5.c381
-rw-r--r--tools/wrt350nv2-builder/src/md5.h91
-rw-r--r--tools/wrt350nv2-builder/src/upgrade.h77
-rw-r--r--tools/wrt350nv2-builder/src/wrt350nv2-builder.c1126
-rw-r--r--tools/xz/Makefile29
-rw-r--r--tools/xz/patches/100-freebsd-compat.patch11
-rw-r--r--tools/yaffs2/Makefile39
-rw-r--r--tools/yaffs2/patches/100-compile.patch125
-rw-r--r--tools/yaffs2/patches/110-openbsd-compat.patch14
302 files changed, 56384 insertions, 0 deletions
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..df384d4
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,125 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Main makefile for the host tools
+#
+curdir:=tools
+
+# subdirectories to descend into
+tools-y :=
+
+ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
+ BUILD_TOOLCHAIN := y
+endif
+ifdef CONFIG_GCC_USE_GRAPHITE
+ ifeq ($(CONFIG_GCC_USE_SYSTEM_PPL_CLOOG),)
+ BUILD_PPL_CLOOG = y
+ endif
+endif
+ifneq ($(CONFIG_PACKAGE_kmod-b43)$(CONFIG_PACKAGE_kmod-b43legacy)$(CONFIG_BRCMSMAC_USE_FW_FROM_WL),)
+ BUILD_B43_TOOLS = y
+endif
+
+tools-$(BUILD_TOOLCHAIN) += gmp mpfr mpc libelf expat
+tools-y += m4 libtool autoconf automake flex bison pkg-config sed mklibs
+tools-y += sstrip make-ext4fs e2fsprogs mtd-utils mkimage
+tools-y += firmware-utils patch-image patch quilt yaffs2 flock padjffs2
+tools-y += mm-macros missing-macros xz cmake scons bc findutils gengetopt patchelf
+tools-$(CONFIG_TARGET_orion_generic) += wrt350nv2-builder upslug2
+tools-$(CONFIG_powerpc) += upx
+tools-$(CONFIG_TARGET_x86) += qemu
+tools-$(CONFIG_TARGET_mxs) += elftosb sdimage
+tools-$(CONFIG_TARGET_brcm2708)$(CONFIG_TARGET_sunxi)$(CONFIG_TARGET_mxs) += mtools dosfstools
+tools-$(CONFIG_TARGET_ar71xx) += lzma-old squashfs
+tools-y += lzma squashfs4
+tools-$(BUILD_B43_TOOLS) += b43-tools
+tools-$(BUILD_PPL_CLOOG) += ppl cloog
+tools-$(CONFIG_USE_SPARSE) += sparse
+
+# builddir dependencies
+$(curdir)/bison/compile := $(curdir)/flex/install
+$(curdir)/flex/compile := $(curdir)/libtool/install
+$(curdir)/pkg-config/compile := $(curdir)/sed/install
+$(curdir)/libtool/compile := $(curdir)/sed/install $(curdir)/m4/install $(curdir)/autoconf/install $(curdir)/automake/install $(curdir)/missing-macros/install
+$(curdir)/squashfs/compile := $(curdir)/lzma-old/install
+$(curdir)/squashfs4/compile := $(curdir)/xz/install
+$(curdir)/quilt/compile := $(curdir)/sed/install $(curdir)/autoconf/install $(curdir)/findutils/install
+$(curdir)/autoconf/compile := $(curdir)/m4/install
+$(curdir)/automake/compile := $(curdir)/m4/install $(curdir)/autoconf/install $(curdir)/pkg-config/install $(curdir)/xz/install
+$(curdir)/gmp/compile := $(curdir)/libtool/install
+$(curdir)/mpc/compile := $(curdir)/mpfr/install $(curdir)/gmp/install
+$(curdir)/mpfr/compile := $(curdir)/gmp/install
+$(curdir)/ppl/compile := $(curdir)/gmp/install
+$(curdir)/cloog/compile := $(curdir)/ppl/install
+$(curdir)/mtd-utils/compile := $(curdir)/e2fsprogs/install $(curdir)/xz/install
+$(curdir)/mkimage/compile := $(curdir)/sed/install
+$(curdir)/mklibs/compile := $(curdir)/libtool/install
+$(curdir)/qemu/compile := $(curdir)/e2fsprogs/install
+$(curdir)/upslug2/compile := $(curdir)/libtool/install
+$(curdir)/mm-macros/compile := $(curdir)/libtool/install
+$(curdir)/missing-macros/compile := $(curdir)/autoconf/install
+$(curdir)/e2fsprogs/compile := $(curdir)/libtool/install
+$(curdir)/libelf/compile := $(curdir)/libtool/install
+$(curdir)/sdcc/compile := $(curdir)/bison/install
+$(curdir)/b43-tools/compile := $(curdir)/bison/install
+$(curdir)/padjffs2/compile := $(curdir)/findutils/install
+$(curdir)/cloog/compile := $(curdir)/ppl/install
+$(curdir)/bc/compile := $(curdir)/bison/install
+$(curdir)/findutils/compile := $(curdir)/bison/install
+$(curdir)/gengetopt/compile := $(curdir)/libtool/install
+$(curdir)/patchelf/compile := $(curdir)/libtool/install
+
+ifneq ($(CONFIG_CCACHE)$(CONFIG_SDK),)
+$(foreach tool, $(filter-out patch,$(tools-y)), $(eval $(curdir)/$(tool)/compile += $(curdir)/ccache/install))
+tools-y += ccache
+endif
+
+# in case there is no patch tool on the host we need to make patch tool a
+# dependency for tools which have patches directory
+$(foreach tool, $(tools-y), $(if $(wildcard $(curdir)/$(tool)/patches),$(eval $(curdir)/$(tool)/compile += $(curdir)/patch/install)))
+
+$(foreach tool, $(tools-y), $(eval $(curdir)/$(tool)/compile += $(curdir)/tar/install))
+tools-y += tar
+
+$(curdir)/builddirs := $(tools-y) $(tools-dep) $(tools-)
+$(curdir)/builddirs-default := $(tools-y)
+
+ifndef DUMP_TARGET_DB
+define PrepareStaging
+ @for dir in $(1); do ( \
+ $(if $(QUIET),,set -x;) \
+ mkdir -p "$$dir"; \
+ cd "$$dir"; \
+ mkdir -p bin lib include stamp; \
+ ); done
+endef
+
+# preparatory work
+$(STAGING_DIR)/.prepared: $(TMP_DIR)/.build
+ $(call PrepareStaging,$(STAGING_DIR))
+ mkdir -p $(BUILD_DIR)/stamp
+ touch $@
+
+$(STAGING_DIR_HOST)/.prepared: $(TMP_DIR)/.build
+ $(call PrepareStaging,$(STAGING_DIR_HOST))
+ mkdir -p $(BUILD_DIR_HOST)/stamp $(STAGING_DIR_HOST)/include/sys
+ $(INSTALL_DATA) $(TOPDIR)/tools/include/*.h $(STAGING_DIR_HOST)/include/
+ $(INSTALL_DATA) $(TOPDIR)/tools/include/sys/*.h $(STAGING_DIR_HOST)/include/sys/
+ ln -sf lib $(STAGING_DIR_HOST)/lib64
+ touch $@
+
+endif
+
+$(curdir)//prepare = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared
+$(curdir)//compile = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared
+
+# prerequisites for the individual targets
+$(curdir)/ := .config prereq
+$(curdir)//install = $(1)/compile
+
+tools_enabled = $(foreach tool,$(sort $(tools-y) $(tools-)),$(if $(filter $(tool),$(tools-y)),y,n))
+$(eval $(call stampfile,$(curdir),tools,install,,_$(subst $(space),,$(tools_enabled))))
+$(eval $(call subdir,$(curdir)))
diff --git a/tools/autoconf/Makefile b/tools/autoconf/Makefile
new file mode 100644
index 0000000..c45855c
--- /dev/null
+++ b/tools/autoconf/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=autoconf
+PKG_VERSION:=2.69
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/autoconf
+PKG_MD5SUM:=50f97f4159805e374639a73e2636f22e
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += \
+ --datarootdir=$(STAGING_DIR_HOST)/share
+
+HOST_CONFIGURE_VARS += \
+ PERL="/usr/bin/env perl"
+
+define Host/Compile
+ export SHELL="$(BASH)"; $(MAKE) -C $(HOST_BUILD_DIR)
+endef
+
+define Host/Install
+ export SHELL="$(BASH)"; $(MAKE) -C $(HOST_BUILD_DIR) install
+endef
+
+define Host/Clean
+ -export SHELL="$(BASH)"; $(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/autoconf/patches/000-relocatable.patch b/tools/autoconf/patches/000-relocatable.patch
new file mode 100644
index 0000000..12e94ae
--- /dev/null
+++ b/tools/autoconf/patches/000-relocatable.patch
@@ -0,0 +1,229 @@
+--- a/bin/autoheader.in
++++ b/bin/autoheader.in
+@@ -28,7 +28,8 @@ eval 'case $# in 0) exec @PERL@ -S "$0";
+
+ BEGIN
+ {
+- my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
++ my $pkgdatadir = $ENV{'autom4te_perllibdir'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ unshift @INC, "$pkgdatadir";
+
+ # Override SHELL. On DJGPP SHELL may not be set to a shell
+@@ -50,7 +51,7 @@ use strict;
+ use vars qw ($config_h %verbatim %symbol);
+
+ # Lib files.
+-my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
++my $autom4te = $ENV{'AUTOM4TE'} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/@autom4te-name@' : '@bindir@/@autom4te-name@');
+ local $config_h;
+ my $config_h_in;
+ my @prepend_include;
+--- a/bin/autom4te.in
++++ b/bin/autom4te.in
+@@ -1,10 +1,12 @@
+-#! @PERL@ -w
++#! @PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ # autom4te - Wrapper around M4 libraries.
+ # Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc.
+
+@@ -24,7 +26,8 @@ eval 'case $# in 0) exec @PERL@ -S "$0";
+
+ BEGIN
+ {
+- my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
++ my $pkgdatadir = $ENV{'autom4te_perllibdir'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ unshift @INC, $pkgdatadir;
+
+ # Override SHELL. On DJGPP SHELL may not be set to a shell
+@@ -44,7 +47,8 @@ use File::Basename;
+ use strict;
+
+ # Data directory.
+-my $pkgdatadir = $ENV{'AC_MACRODIR'} || '@pkgdatadir@';
++my $pkgdatadir = $ENV{'AC_MACRODIR'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+
+ # $LANGUAGE{LANGUAGE} -- Automatic options for LANGUAGE.
+ my %language;
+@@ -87,7 +91,7 @@ my @include;
+ my $freeze = 0;
+
+ # $M4.
+-my $m4 = $ENV{"M4"} || '@M4@';
++my $m4 = $ENV{"M4"} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/m4' : '@M4@');
+ # Some non-GNU m4's don't reject the --help option, so give them /dev/null.
+ fatal "need GNU m4 1.4 or later: $m4"
+ if system "$m4 --help </dev/null 2>&1 | grep reload-state >/dev/null";
+@@ -269,6 +273,12 @@ sub load_configuration ($)
+
+ my @words = shellwords ($_);
+ my $type = shift @words;
++
++ if ($ENV{'STAGING_DIR'})
++ {
++ @words = map { s!^@pkgdatadir@!$ENV{'STAGING_DIR'}/../host/share/autoconf!; $_ } @words;
++ }
++
+ if ($type eq 'begin-language:')
+ {
+ fatal "$file:$.: end-language missing for: $lang"
+--- a/bin/autoreconf.in
++++ b/bin/autoreconf.in
+@@ -1,10 +1,12 @@
+-#! @PERL@ -w
++#! @PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ # autoreconf - install the GNU Build System in a directory tree
+ # Copyright (C) 1994, 1999-2012 Free Software Foundation, Inc.
+
+@@ -26,7 +28,8 @@ eval 'case $# in 0) exec @PERL@ -S "$0";
+
+ BEGIN
+ {
+- my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
++ my $pkgdatadir = $ENV{'autom4te_perllibdir'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ unshift @INC, $pkgdatadir;
+
+ # Override SHELL. On DJGPP SHELL may not be set to a shell
+@@ -106,9 +109,9 @@ Written by David J. MacKenzie and Akim D
+ ";
+
+ # Lib files.
+-my $autoconf = $ENV{'AUTOCONF'} || '@bindir@/@autoconf-name@';
+-my $autoheader = $ENV{'AUTOHEADER'} || '@bindir@/@autoheader-name@';
+-my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
++my $autoconf = $ENV{'AUTOCONF'} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/@autoconf-name@' : '@bindir@/@autoconf-name@');
++my $autoheader = $ENV{'AUTOHEADER'} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/@autoheader-name@' : '@bindir@/@autoheader-name@');
++my $autom4te = $ENV{'AUTOM4TE'} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/@autom4te-name@' : '@bindir@/@autom4te-name@');
+ my $automake = $ENV{'AUTOMAKE'} || 'automake';
+ my $aclocal = $ENV{'ACLOCAL'} || 'aclocal';
+ my $libtoolize = $ENV{'LIBTOOLIZE'} || 'libtoolize';
+--- a/bin/autoscan.in
++++ b/bin/autoscan.in
+@@ -1,4 +1,4 @@
+-#! @PERL@ -w
++#! @PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+@@ -23,9 +23,12 @@
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ BEGIN
+ {
+- my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
++ my $pkgdatadir = $ENV{'autom4te_perllibdir'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ unshift @INC, $pkgdatadir;
+
+ # Override SHELL. On DJGPP SHELL may not be set to a shell
+@@ -91,10 +94,10 @@ my $configure_scan = 'configure.scan';
+ my $log;
+
+ # Autoconf and lib files.
+-my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
++my $autom4te = $ENV{'AUTOM4TE'} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/@autom4te-name@' : '@bindir@/@autom4te-name@');
+ my $autoconf = "$autom4te --language=autoconf";
+ my @prepend_include;
+-my @include = ('@pkgdatadir@');
++my @include = ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+
+ # $help
+ # -----
+--- a/bin/autoupdate.in
++++ b/bin/autoupdate.in
+@@ -1,4 +1,4 @@
+-#! @PERL@ -w
++#! @PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+@@ -24,9 +24,12 @@
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ BEGIN
+ {
+- my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
++ my $pkgdatadir = $ENV{'autom4te_perllibdir'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ unshift @INC, $pkgdatadir;
+
+ # Override SHELL. On DJGPP SHELL may not be set to a shell
+@@ -50,10 +53,10 @@ my $autom4te = $ENV{'AUTOM4TE'} || '@bin
+ my $autoconf = "$autom4te --language=autoconf";
+ # We need to find m4sugar.
+ my @prepend_include;
+-my @include = ('@pkgdatadir@');
++my @include = ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ my $force = 0;
+ # m4.
+-my $m4 = $ENV{"M4"} || '@M4@';
++my $m4 = $ENV{"M4"} || ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/bin/m4' : '@M4@');
+
+
+ # $HELP
+--- a/bin/ifnames.in
++++ b/bin/ifnames.in
+@@ -1,10 +1,12 @@
+-#! @PERL@ -w
++#! @PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ # ifnames - print the identifiers used in C preprocessor conditionals
+
+ # Copyright (C) 1994-1995, 1999-2003, 2005-2012 Free Software
+@@ -31,7 +33,8 @@ eval 'case $# in 0) exec @PERL@ -S "$0";
+
+ BEGIN
+ {
+- my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
++ my $pkgdatadir = $ENV{'autom4te_perllibdir'} ||
++ ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/autoconf' : '@pkgdatadir@');
+ unshift @INC, $pkgdatadir;
+
+ # Override SHELL. On DJGPP SHELL may not be set to a shell
+--- a/bin/autoconf.as
++++ b/bin/autoconf.as
+@@ -84,7 +84,11 @@ exit_missing_arg='
+ # restore font-lock: '
+
+ # Variables.
+-: ${AUTOM4TE='@bindir@/@autom4te-name@'}
++if test -n "$STAGING_DIR"; then
++ : ${AUTOM4TE="$STAGING_DIR/../host/bin/@autom4te-name@"}
++else
++ : ${AUTOM4TE='@bindir@/@autom4te-name@'}
++fi
+ autom4te_options=
+ outfile=
+ verbose=false
diff --git a/tools/autoconf/patches/001-no_emacs_lib.patch b/tools/autoconf/patches/001-no_emacs_lib.patch
new file mode 100644
index 0000000..35c5164
--- /dev/null
+++ b/tools/autoconf/patches/001-no_emacs_lib.patch
@@ -0,0 +1,22 @@
+--- a/lib/Makefile.am
++++ b/lib/Makefile.am
+@@ -15,7 +15,7 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+-SUBDIRS = Autom4te m4sugar autoconf autotest autoscan emacs
++SUBDIRS = Autom4te m4sugar autoconf autotest autoscan
+ nodist_pkgdata_DATA = autom4te.cfg
+ EXTRA_DIST = autom4te.in freeze.mk
+
+--- a/lib/Makefile.in
++++ b/lib/Makefile.in
+@@ -225,7 +225,7 @@ target_alias = @target_alias@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = Autom4te m4sugar autoconf autotest autoscan emacs
++SUBDIRS = Autom4te m4sugar autoconf autotest autoscan
+ nodist_pkgdata_DATA = autom4te.cfg
+ EXTRA_DIST = autom4te.in freeze.mk
+ edit = sed \
diff --git a/tools/autoconf/patches/002-musl_host_fixup.patch b/tools/autoconf/patches/002-musl_host_fixup.patch
new file mode 100644
index 0000000..4dcb1ec
--- /dev/null
+++ b/tools/autoconf/patches/002-musl_host_fixup.patch
@@ -0,0 +1,24 @@
+--- a/build-aux/config.sub
++++ b/build-aux/config.sub
+@@ -122,9 +122,9 @@ esac
+ # Here we must recognize all the valid KERNEL-OS combinations.
+ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+ case $maybe_os in
+- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+- knetbsd*-gnu* | netbsd*-gnu* | \
++ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-musl* | \
++ linux-newlib* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
++ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+@@ -1360,7 +1360,7 @@ case $os in
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-android* \
+- | -linux-newlib* | -linux-uclibc* \
++ | -linux-musl* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff --git a/tools/automake/Makefile b/tools/automake/Makefile
new file mode 100644
index 0000000..0eea101
--- /dev/null
+++ b/tools/automake/Makefile
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=automake
+PKG_VERSION:=1.15
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/automake
+PKG_MD5SUM:=9a1ddb0e053474d9d1105cfe39b0c48d
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += \
+ --datarootdir=$(STAGING_DIR_HOST)/share \
+ --disable-silent-rules
+
+HOST_CONFIGURE_VARS += \
+ PERL="/usr/bin/env perl" \
+ am_cv_prog_PERL_ithreads=no
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR); $(AM_TOOL_PATHS) STAGING_DIR="" ./bootstrap.sh)
+ $(call Host/Configure/Default)
+endef
+
+define Host/Install
+ # remove old automake resources to avoid version conflicts
+ rm -rf $(STAGING_DIR_HOST)/share/aclocal-[0-9]*
+ rm -rf $(STAGING_DIR_HOST)/share/automake-[0-9]*
+ $(MAKE) -C $(HOST_BUILD_DIR) install
+ mv $(STAGING_DIR_HOST)/bin/aclocal $(STAGING_DIR_HOST)/bin/aclocal.real
+ $(INSTALL_BIN) ./files/aclocal $(STAGING_DIR_HOST)/bin
+ ln -sf aclocal $(STAGING_DIR_HOST)/bin/aclocal-1.9
+ ln -sf aclocal $(STAGING_DIR_HOST)/bin/aclocal-1.10
+ ln -sf aclocal $(STAGING_DIR_HOST)/bin/aclocal-1.11
+ ln -sf aclocal $(STAGING_DIR_HOST)/bin/aclocal-1.11.6
+ ln -sf aclocal $(STAGING_DIR_HOST)/bin/aclocal-1.15
+endef
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/automake/files/aclocal b/tools/automake/files/aclocal
new file mode 100755
index 0000000..a60df10
--- /dev/null
+++ b/tools/automake/files/aclocal
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+aclocal.real $ACLOCAL_INCLUDE $@
diff --git a/tools/automake/patches/000-relocatable.patch b/tools/automake/patches/000-relocatable.patch
new file mode 100644
index 0000000..59864f2
--- /dev/null
+++ b/tools/automake/patches/000-relocatable.patch
@@ -0,0 +1,96 @@
+--- a/lib/Automake/Config.in
++++ b/lib/Automake/Config.in
+@@ -32,7 +32,7 @@ our $PACKAGE = '@PACKAGE@';
+ our $PACKAGE_BUGREPORT = '@PACKAGE_BUGREPORT@';
+ our $VERSION = '@VERSION@';
+ our $RELEASE_YEAR = '@RELEASE_YEAR@';
+-our $libdir = '@datadir@/@PACKAGE@-@APIVERSION@';
++our $libdir = $ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/@PACKAGE@-@APIVERSION@' : '@datadir@/@PACKAGE@-@APIVERSION@';
+
+ our $perl_threads = 0;
+ # We need at least this version for CLONE support.
+--- a/bin/aclocal.in
++++ b/bin/aclocal.in
+@@ -1,10 +1,12 @@
+-#!@PERL@ -w
++#!@PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ # aclocal - create aclocal.m4 by scanning configure.ac
+
+ # Copyright (C) 1996-2014 Free Software Foundation, Inc.
+@@ -27,7 +29,7 @@ eval 'case $# in 0) exec @PERL@ -S "$0";
+
+ BEGIN
+ {
+- @Aclocal::perl_libdirs = ('@datadir@/@PACKAGE@-@APIVERSION@')
++ @Aclocal::perl_libdirs = ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/@PACKAGE@-@APIVERSION@' : '@datadir@/@PACKAGE@-@APIVERSION@')
+ unless @Aclocal::perl_libdirs;
+ unshift @INC, @Aclocal::perl_libdirs;
+ }
+@@ -69,8 +71,8 @@ $perl_threads = 0;
+ # ACLOCAL_PATH environment variable, and reset with the '--system-acdir'
+ # option.
+ my @user_includes = ();
+-my @automake_includes = ("@datadir@/aclocal-$APIVERSION");
+-my @system_includes = ('@datadir@/aclocal');
++my @automake_includes = ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . "/../host/share/aclocal-$APIVERSION" : "@datadir@/aclocal-$APIVERSION");
++my @system_includes = ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/aclocal' : '@datadir@/aclocal');
+
+ # Whether we should copy M4 file in $user_includes[0].
+ my $install = 0;
+--- a/bin/automake.in
++++ b/bin/automake.in
+@@ -1,10 +1,12 @@
+-#!@PERL@ -w
++#!@PERL@
+ # -*- perl -*-
+ # @configure_input@
+
+ eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
+ if 0;
+
++$^W = 1;
++
+ # automake - create Makefile.in from Makefile.am
+ # Copyright (C) 1994-2014 Free Software Foundation, Inc.
+
+@@ -31,7 +33,7 @@ use strict;
+
+ BEGIN
+ {
+- @Automake::perl_libdirs = ('@datadir@/@PACKAGE@-@APIVERSION@')
++ @Automake::perl_libdirs = ($ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/@PACKAGE@-@APIVERSION@' : '@datadir@/@PACKAGE@-@APIVERSION@')
+ unless @Automake::perl_libdirs;
+ unshift @INC, @Automake::perl_libdirs;
+
+--- a/t/wrap/aclocal.in
++++ b/t/wrap/aclocal.in
+@@ -1,6 +1,8 @@
+-#!@PERL@ -w
++#!@PERL@
+ # @configure_input@
+
++$^W = 1;
++
+ # Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+ # This program is free software; you can redistribute it and/or modify
+--- a/t/wrap/automake.in
++++ b/t/wrap/automake.in
+@@ -1,6 +1,8 @@
+-#!@PERL@ -w
++#!@PERL@
+ # @configure_input@
+
++$^W = 1;
++
+ # Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+ # This program is free software; you can redistribute it and/or modify
diff --git a/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch b/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch
new file mode 100644
index 0000000..ad019dd
--- /dev/null
+++ b/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch
@@ -0,0 +1,15 @@
+--- a/bin/aclocal.in
++++ b/bin/aclocal.in
+@@ -356,6 +356,12 @@ sub scan_m4_dirs ($$@)
+
+ foreach my $m4dir (@dirlist)
+ {
++ if (! -d $m4dir)
++ {
++ msg ('override', "warning: skipping not existing directory `$m4dir'");
++ next;
++ }
++
+ if (! opendir (DIR, $m4dir))
+ {
+ # TODO: maybe avoid complaining only if errno == ENONENT?
diff --git a/tools/automake/patches/200-do-not-override-silent-rules.patch b/tools/automake/patches/200-do-not-override-silent-rules.patch
new file mode 100644
index 0000000..e8ba8c5
--- /dev/null
+++ b/tools/automake/patches/200-do-not-override-silent-rules.patch
@@ -0,0 +1,13 @@
+diff -ruN automake-1.15/m4/silent.m4 automake-1.15.mod/m4/silent.m4
+--- automake-1.15/m4/silent.m4 2014-12-30 22:53:05.000000000 +0100
++++ automake-1.15.mod/m4/silent.m4 2015-03-11 12:00:26.280586399 +0100
+@@ -41,7 +41,8 @@
+ else
+ am_cv_make_support_nested_variables=no
+ fi])
+-if test $am_cv_make_support_nested_variables = yes; then
++#if test $am_cv_make_support_nested_variables = yes; then
++if false; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
diff --git a/tools/b43-tools/Makefile b/tools/b43-tools/Makefile
new file mode 100644
index 0000000..28a33d6
--- /dev/null
+++ b/tools/b43-tools/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=b43-tools
+PKG_VERSION:=019
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://github.com/mbuesch/b43-tools.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)
+PKG_SOURCE_VERSION:=8dce53297966b31b6c70a7a03c2433978dd9f288
+#PKG_MIRROR_MD5SUM:=50ca3c763ee21ee213addd17cf1c1b86
+HOST_BUILD_DIR=$(BUILD_DIR_HOST)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+
+define Host/Compile
+ +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR)/fwcutter \
+ CFLAGS="$(HOST_CFLAGS) -include endian.h" \
+ $(HOST_MAKE_FLAGS) \
+ $(1) QUIET_SPARSE=:
+ +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR)/assembler \
+ CFLAGS="$(HOST_CFLAGS) -include endian.h" \
+ $(HOST_MAKE_FLAGS) \
+ LDFLAGS= \
+ $(1) QUIET_SPARSE=:
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/fwcutter/b43-fwcutter $(STAGING_DIR_HOST)/bin/
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/assembler/b43-asm $(STAGING_DIR_HOST)/bin/
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/assembler/b43-asm.bin $(STAGING_DIR_HOST)/bin/
+ $(INSTALL_BIN) ./files/b43-fwsquash.py $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/b43-fwcutter
+ rm -f $(STAGING_DIR_HOST)/bin/b43-asm
+ rm -f $(STAGING_DIR_HOST)/bin/b43-asm.bin
+ rm -f $(STAGING_DIR_HOST)/bin/b43-fwsquash.py
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/b43-tools/files/b43-fwsquash.py b/tools/b43-tools/files/b43-fwsquash.py
new file mode 100755
index 0000000..2946d7c
--- /dev/null
+++ b/tools/b43-tools/files/b43-fwsquash.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+#
+# b43 firmware file squasher
+# Removes unnecessary firmware files
+#
+# Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
+#
+# Licensed under the GNU/GPL version 2 or (at your option) any later version.
+#
+
+import sys
+import os
+
+def usage():
+ print("Usage: %s PHYTYPES COREREVS /path/to/extracted/firmware" % sys.argv[0])
+ print("")
+ print("PHYTYPES is a comma separated list of:")
+ print("A => A-PHY")
+ print("AG => Dual A-PHY G-PHY")
+ print("G => G-PHY")
+ print("LP => LP-PHY")
+ print("N => N-PHY")
+ print("HT => HT-PHY")
+ print("LCN => LCN-PHY")
+ print("LCN40 => LCN40-PHY")
+ print("AC => AC-PHY")
+ print("")
+ print("COREREVS is a comma separated list of core revision numbers.")
+
+if len(sys.argv) != 4:
+ usage()
+ sys.exit(1)
+
+phytypes = sys.argv[1]
+corerevs = sys.argv[2]
+fwpath = sys.argv[3]
+
+phytypes = phytypes.split(',')
+try:
+ corerevs = map(lambda r: int(r), corerevs.split(','))
+except ValueError:
+ print("ERROR: \"%s\" is not a valid COREREVS string\n" % corerevs)
+ usage()
+ sys.exit(1)
+
+
+fwfiles = os.listdir(fwpath)
+fwfiles = filter(lambda str: str.endswith(".fw"), fwfiles)
+if not fwfiles:
+ print("ERROR: No firmware files found in %s" % fwpath)
+ sys.exit(1)
+
+required_fwfiles = []
+
+def revs_match(revs_a, revs_b):
+ for rev in revs_a:
+ if rev in revs_b:
+ return True
+ return False
+
+def phytypes_match(types_a, types_b):
+ for type in types_a:
+ type = type.strip().upper()
+ if type in types_b:
+ return True
+ return False
+
+revmapping = {
+ "ucode2.fw" : ( (2,3,), ("G",), ),
+ "ucode4.fw" : ( (4,), ("G",), ),
+ "ucode5.fw" : ( (5,6,7,8,9,10,), ("G","A","AG",), ),
+ "ucode11.fw" : ( (11,12,), ("N",), ),
+ "ucode13.fw" : ( (13,), ("LP","G",), ),
+ "ucode14.fw" : ( (14,), ("LP",), ),
+ "ucode15.fw" : ( (15,), ("LP",), ),
+ "ucode16_mimo.fw" : ( (16,17,18,19,23,), ("N",), ),
+# "ucode16_lp.fw" : ( (16,17,18,19,), ("LP",), ),
+ "ucode24_lcn.fw" : ( (24,), ("LCN",), ),
+ "ucode25_mimo.fw" : ( (25,28,), ("N",), ),
+ "ucode25_lcn.fw" : ( (25,28,), ("LCN",), ),
+ "ucode26_mimo.fw" : ( (26,), ("HT",), ),
+ "ucode29_mimo.fw" : ( (29,), ("HT",), ),
+ "ucode30_mimo.fw" : ( (30,), ("N",), ),
+ "ucode33_lcn40.fw" : ( (33,), ("LCN40",), ),
+ "ucode40.fw" : ( (40,), ("AC",), ),
+ "ucode42.fw" : ( (42,), ("AC",), ),
+ "pcm4.fw" : ( (1,2,3,4,), ("G",), ),
+ "pcm5.fw" : ( (5,6,7,8,9,10,), ("G","A","AG",), ),
+}
+
+initvalmapping = {
+ "a0g1initvals5.fw" : ( (5,6,7,8,9,10,), ("AG",), ),
+ "a0g0initvals5.fw" : ( (5,6,7,8,9,10,), ("A", "AG",), ),
+ "b0g0initvals2.fw" : ( (2,4,), ("G",), ),
+ "b0g0initvals5.fw" : ( (5,6,7,8,9,10,), ("G",), ),
+ "b0g0initvals13.fw" : ( (13,), ("G",), ),
+ "n0initvals11.fw" : ( (11,12,), ("N",), ),
+ "n0initvals16.fw" : ( (16,17,18,23,), ("N",), ),
+ "n0initvals24.fw" : ( (24,), ("N",), ),
+ "n0initvals25.fw" : ( (25,28,), ("N",), ),
+ "n16initvals30.fw" : ( (30,), ("N",), ),
+ "lp0initvals13.fw" : ( (13,), ("LP",), ),
+ "lp0initvals14.fw" : ( (14,), ("LP",), ),
+ "lp0initvals15.fw" : ( (15,), ("LP",), ),
+# "lp0initvals16.fw" : ( (16,17,18,), ("LP",), ),
+ "lcn0initvals24.fw" : ( (24,), ("LCN",), ),
+ "ht0initvals26.fw" : ( (26,), ("HT",), ),
+ "ht0initvals29.fw" : ( (29,), ("HT",), ),
+ "lcn400initvals33.fw" : ( (33,), ("LCN40",), ),
+ "ac0initvals40.fw" : ( (40,), ("AC",), ),
+ "ac1initvals42.fw" : ( (42,), ("AC",), ),
+ "a0g1bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("AG",), ),
+ "a0g0bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("A", "AG"), ),
+ "b0g0bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("G",), ),
+ "n0bsinitvals11.fw" : ( (11,12,), ("N",), ),
+ "n0bsinitvals16.fw" : ( (16,17,18,23,), ("N",), ),
+ "n0bsinitvals24.fw" : ( (24,), ("N",), ),
+ "n0bsinitvals25.fw" : ( (25,28,), ("N",), ),
+ "n16bsinitvals30.fw" : ( (30,), ("N",), ),
+ "lp0bsinitvals13.fw" : ( (13,), ("LP",), ),
+ "lp0bsinitvals14.fw" : ( (14,), ("LP",), ),
+ "lp0bsinitvals15.fw" : ( (15,), ("LP",), ),
+# "lp0bsinitvals16.fw" : ( (16,17,18,), ("LP",), ),
+ "lcn0bsinitvals24.fw" : ( (24,), ("LCN",), ),
+ "ht0bsinitvals26.fw" : ( (26,), ("HT",), ),
+ "ht0bsinitvals29.fw" : ( (29,), ("HT",), ),
+ "lcn400bsinitvals33.fw" : ( (33,), ("LCN40",), ),
+ "ac0bsinitvals40.fw" : ( (40,), ("AC",), ),
+ "ac1bsinitvals42.fw" : ( (42,), ("AC",), ),
+}
+
+for f in fwfiles:
+ if f in revmapping:
+ if revs_match(corerevs, revmapping[f][0]) and\
+ phytypes_match(phytypes, revmapping[f][1]):
+ required_fwfiles += [f]
+ continue
+ if f in initvalmapping:
+ if revs_match(corerevs, initvalmapping[f][0]) and\
+ phytypes_match(phytypes, initvalmapping[f][1]):
+ required_fwfiles += [f]
+ continue
+ print("WARNING: Firmware file %s not found in the mapping lists" % f)
+
+for f in fwfiles:
+ if f not in required_fwfiles:
+ print("Deleting %s" % f)
+ os.unlink(fwpath + '/' + f)
+
diff --git a/tools/b43-tools/patches/001-fw-dirname.patch b/tools/b43-tools/patches/001-fw-dirname.patch
new file mode 100644
index 0000000..1fd4c66
--- /dev/null
+++ b/tools/b43-tools/patches/001-fw-dirname.patch
@@ -0,0 +1,16 @@
+--- a/fwcutter/fwcutter.c
++++ b/fwcutter/fwcutter.c
+@@ -50,13 +50,8 @@
+ #include "fwcutter.h"
+ #include "fwcutter_list.h"
+
+-#if defined(__DragonFly__) || defined(__FreeBSD__)
+-#define V3_FW_DIRNAME "v3"
+-#define V4_FW_DIRNAME "v4"
+-#else
+ #define V3_FW_DIRNAME "b43legacy"
+ #define V4_FW_DIRNAME "b43"
+-#endif
+
+ static struct cmdline_args cmdargs;
+
diff --git a/tools/b43-tools/patches/002-no_libfl.patch b/tools/b43-tools/patches/002-no_libfl.patch
new file mode 100644
index 0000000..2e55b08
--- /dev/null
+++ b/tools/b43-tools/patches/002-no_libfl.patch
@@ -0,0 +1,14 @@
+--- a/assembler/main.c
++++ b/assembler/main.c
+@@ -1268,6 +1268,11 @@ static void initialize(void)
+ #endif /* YYDEBUG */
+ }
+
++int yywrap(void)
++{
++ return 1;
++}
++
+ int main(int argc, char **argv)
+ {
+ int err, res = 1;
diff --git a/tools/bc/Makefile b/tools/bc/Makefile
new file mode 100644
index 0000000..2e99b43
--- /dev/null
+++ b/tools/bc/Makefile
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bc
+PKG_VERSION:=1.06.95
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://alpha.gnu.org/gnu/bc \
+ http://gnualpha.uib.no/bc/ \
+ http://mirrors.fe.up.pt/pub/gnu-alpha/bc/ \
+ http://www.nic.funet.fi/pub/gnu/alpha/gnu/bc/
+PKG_MD5SUM:=5126a721b73f97d715bb72c13c889035
+
+include $(INCLUDE_DIR)/host-build.mk
+
+$(eval $(call HostBuild))
diff --git a/tools/bc/patches/001-no_doc.patch b/tools/bc/patches/001-no_doc.patch
new file mode 100644
index 0000000..50deee8
--- /dev/null
+++ b/tools/bc/patches/001-no_doc.patch
@@ -0,0 +1,23 @@
+diff -urN bc-1.06.95/Makefile.am bc-1.06.95.new/Makefile.am
+--- bc-1.06.95/Makefile.am 2005-05-27 01:05:41.000000000 +0100
++++ bc-1.06.95.new/Makefile.am 2013-07-09 09:33:31.521490710 +0100
+@@ -1,6 +1,6 @@
+ ## Process this file with automake to produce Makefile.in
+
+-SUBDIRS = lib bc dc doc
++SUBDIRS = lib bc dc
+
+ MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
+ stamp-h $(distdir).tar.gz h/number.h depcomp missing
+diff -urN bc-1.06.95/Makefile.in bc-1.06.95.new/Makefile.in
+--- bc-1.06.95/Makefile.in 2006-09-05 03:39:30.000000000 +0100
++++ bc-1.06.95.new/Makefile.in 2013-07-09 09:33:28.565490767 +0100
+@@ -149,7 +149,7 @@
+ sharedstatedir = @sharedstatedir@
+ sysconfdir = @sysconfdir@
+ target_alias = @target_alias@
+-SUBDIRS = lib bc dc doc
++SUBDIRS = lib bc dc
+ MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
+ stamp-h $(distdir).tar.gz h/number.h depcomp missing
+
diff --git a/tools/bison/Makefile b/tools/bison/Makefile
new file mode 100644
index 0000000..b8ad32c
--- /dev/null
+++ b/tools/bison/Makefile
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2008-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=bison
+PKG_VERSION:=3.0.4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=c342201de104cc9ce0a21e0ad10d4021
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+define Host/Install
+ $(call Host/Install/Default)
+ $(INSTALL_BIN) ./scripts/yacc $(STAGING_DIR_HOST)/bin/yacc
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/bison/patches/010-intl-stub-compat.patch b/tools/bison/patches/010-intl-stub-compat.patch
new file mode 100644
index 0000000..9823420
--- /dev/null
+++ b/tools/bison/patches/010-intl-stub-compat.patch
@@ -0,0 +1,15 @@
+--- a/src/main.c
++++ b/src/main.c
+@@ -60,9 +60,9 @@
+ {
+ set_program_name (argv[0]);
+ setlocale (LC_ALL, "");
+- (void) bindtextdomain (PACKAGE, LOCALEDIR);
+- (void) bindtextdomain ("bison-runtime", LOCALEDIR);
+- (void) textdomain (PACKAGE);
++ bindtextdomain (PACKAGE, LOCALEDIR);
++ bindtextdomain ("bison-runtime", LOCALEDIR);
++ textdomain (PACKAGE);
+
+ {
+ char const *cp = getenv ("LC_CTYPE");
diff --git a/tools/bison/patches/100-fix-gets-removal.patch b/tools/bison/patches/100-fix-gets-removal.patch
new file mode 100644
index 0000000..20b18cf
--- /dev/null
+++ b/tools/bison/patches/100-fix-gets-removal.patch
@@ -0,0 +1,16 @@
+--- a/lib/stdio.in.h
++++ b/lib/stdio.in.h
+@@ -719,13 +719,6 @@
+ # endif
+ #endif
+
+-/* It is very rare that the developer ever has full control of stdin,
+- so any use of gets warrants an unconditional warning; besides, C11
+- removed it. */
+-#undef gets
+-#if HAVE_RAW_DECL_GETS
+-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
+-#endif
+
+
+ #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
diff --git a/tools/bison/scripts/yacc b/tools/bison/scripts/yacc
new file mode 100755
index 0000000..8f73e26
--- /dev/null
+++ b/tools/bison/scripts/yacc
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec bison -y "$@"
diff --git a/tools/ccache/Makefile b/tools/ccache/Makefile
new file mode 100644
index 0000000..76b6957
--- /dev/null
+++ b/tools/ccache/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/target.mk
+
+PKG_NAME:=ccache
+PKG_VERSION:=3.1.11
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://samba.org/ftp/ccache/
+PKG_MD5SUM:=0f6df80c8941d9020a1fd5df5ad57dd7
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_VARS += CC="$(HOSTCC_NOCACHE)"
+
+define Host/Install/ccache
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin/
+ $(CP) ./files/* $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+define Host/Install
+ $(call Host/Install/Default)
+ $(call Host/Install/ccache)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/ccache/files/ccache_cc b/tools/ccache/files/ccache_cc
new file mode 100755
index 0000000..01c4ad4
--- /dev/null
+++ b/tools/ccache/files/ccache_cc
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec ccache "${TARGET_CC_NOCACHE}" "$@"
diff --git a/tools/ccache/files/ccache_cxx b/tools/ccache/files/ccache_cxx
new file mode 100755
index 0000000..cc60eb3
--- /dev/null
+++ b/tools/ccache/files/ccache_cxx
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec ccache "${TARGET_CXX_NOCACHE}" "$@"
diff --git a/tools/ccache/patches/100-honour-copts.patch b/tools/ccache/patches/100-honour-copts.patch
new file mode 100644
index 0000000..dc32885
--- /dev/null
+++ b/tools/ccache/patches/100-honour-copts.patch
@@ -0,0 +1,33 @@
+From 90762a9b8d9a50b6176f10bd6c2e2b9501117561 Mon Sep 17 00:00:00 2001
+From: Karl Vogel <karl.vogel@gmail.com>
+Date: Tue, 14 Jul 2015 11:05:33 +0200
+Subject: [PATCH] Include environment variable GCC_HONOUR_COPTS in hash.
+
+The OpenWRT patch, 910-mbsd_multi.patch, to GCC adds an extra
+compilation flag, -fhonour-copts, which is influenced by an
+environment variable called GCC_HONOUR_COPTS.
+
+Include this environment var in the hash calculation as otherwise
+the gcc stdout warning from a previous compilation might be shown
+where, even when GCC_HONOUR_COPTS is in 's'ilent mode.
+
+Signed-off-by: Karl Vogel <karl.vogel@gmail.com>
+---
+ ccache.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ccache.c b/ccache.c
+index e41af13..b736a9c 100644
+--- a/ccache.c
++++ b/ccache.c
+@@ -965,6 +965,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode)
+ "CPLUS_INCLUDE_PATH",
+ "OBJC_INCLUDE_PATH",
+ "OBJCPLUS_INCLUDE_PATH", /* clang */
++ "GCC_HONOUR_COPTS",
+ NULL
+ };
+ for (p = envvars; *p != NULL ; ++p) {
+--
+1.9.1
+
diff --git a/tools/cloog/Makefile b/tools/cloog/Makefile
new file mode 100644
index 0000000..b1e6aa4
--- /dev/null
+++ b/tools/cloog/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2009-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cloog
+PKG_VERSION:=0.18.1
+
+PKG_SOURCE_URL:=http://www.bastoul.net/cloog/pages/download/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_MD5SUM:=e34fca0540d840e5d0f6427e98c92252
+
+HOST_FIXUP:=autoreconf
+
+HOST_BUILD_PARALLEL:=1
+HOST_CONFIGURE_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport CFLAGS
+
+HOST_CONFIGURE_VARS += \
+ LIBS=-lstdc++
+
+HOST_CONFIGURE_ARGS += \
+ --enable-static \
+ --disable-shared \
+ --with-ppl=$(BUILD_DIR_HOST)
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR)/$(3); \
+ $(HOST_CONFIGURE_CMD) \
+ $(HOST_CONFIGURE_VARS) \
+ $(HOST_CONFIGURE_ARGS); \
+ )
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/cmake/Makefile b/tools/cmake/Makefile
new file mode 100644
index 0000000..b71f1af
--- /dev/null
+++ b/tools/cmake/Makefile
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=cmake
+PKG_VERSION:=3.3.2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.cmake.org/files/v3.3/ \
+ https://fossies.org/linux/misc/
+PKG_MD5SUM:=5febbd11bcaac854a27eebaf4a124be2
+
+HOST_BUILD_PARALLEL:=1
+HOST_CONFIGURE_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_VARS :=
+
+HOST_CONFIGURE_ARGS := \
+ --prefix=$(STAGING_DIR_HOST) \
+ $(if $(MAKE_JOBSERVER),--parallel="$(MAKE_JOBSERVER)")
+
+$(eval $(call HostBuild))
diff --git a/tools/cmake/patches/100-disable_qt_tests.patch b/tools/cmake/patches/100-disable_qt_tests.patch
new file mode 100644
index 0000000..deaa5ae
--- /dev/null
+++ b/tools/cmake/patches/100-disable_qt_tests.patch
@@ -0,0 +1,31 @@
+--- a/Tests/RunCMake/CMakeLists.txt
++++ b/Tests/RunCMake/CMakeLists.txt
+@@ -160,15 +160,6 @@
+ add_RunCMake_test(no_install_prefix)
+ add_RunCMake_test(configure_file)
+
+-find_package(Qt4 QUIET)
+-find_package(Qt5Core QUIET)
+-if (QT4_FOUND AND Qt5Core_FOUND AND NOT Qt5Core_VERSION VERSION_LESS 5.1.0)
+- add_RunCMake_test(IncompatibleQt)
+-endif()
+-if (QT4_FOUND)
+- add_RunCMake_test(ObsoleteQtMacros -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE})
+-endif()
+-
+ find_package(PkgConfig QUIET)
+ if(PKG_CONFIG_FOUND)
+ add_RunCMake_test(FindPkgConfig)
+--- a/Tests/CMakeLists.txt
++++ b/Tests/CMakeLists.txt
+@@ -358,10 +358,6 @@
+
+ list(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
+
+- if(NOT QT4_FOUND)
+- find_package(Qt4 QUIET)
+- endif()
+-
+ if(QT4_FOUND)
+ # test whether the Qt4 which has been found works, on some machines
+ # which run nightly builds there were errors like "wrong file format"
diff --git a/tools/cmake/patches/110-freebsd-compat.patch b/tools/cmake/patches/110-freebsd-compat.patch
new file mode 100644
index 0000000..9133db5
--- /dev/null
+++ b/tools/cmake/patches/110-freebsd-compat.patch
@@ -0,0 +1,42 @@
+From 6eab64c3adc7a38c322cd4d9a1a1881f2d49cb9c Mon Sep 17 00:00:00 2001
+From: Raphael Kubo da Costa <rakuco@FreeBSD.org>
+Date: Tue, 15 Oct 2013 00:10:56 +0300
+Subject: [PATCH] SystemInformation: Include backtrace-related headers on
+ FreeBSD
+
+This was probably broken for a long while, but the problem was not apparent
+because the check for execinfo.h would fail by default because
+-I/usr/local/include was not being passed to the compiler when making the
+checks for the header's existence.
+
+Now that very recent FreeBSD versions (ie. 10-CURRENT) have NetBSD's
+libexecinfo in base (and it is thus installed into /usr), the
+backtrace-related checks would pass, but the required headers were not being
+included in SystemInformation.cxx.
+
+Change-Id: I3b91ed7ac0e6878035aee202b3336c536cc6d2ff
+---
+ Source/kwsys/SystemInformation.cxx | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
+index 7c31f3a..2672730 100644
+--- a/Source/kwsys/SystemInformation.cxx
++++ b/Source/kwsys/SystemInformation.cxx
+@@ -91,6 +91,15 @@ typedef int siginfo_t;
+ # include <ifaddrs.h>
+ # define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+ # endif
++# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
++# include <execinfo.h>
++# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
++# include <cxxabi.h>
++# endif
++# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
++# include <dlfcn.h>
++# endif
++# endif
+ #endif
+
+ #if defined(__OpenBSD__) || defined(__NetBSD__)
+
diff --git a/tools/dosfstools/Makefile b/tools/dosfstools/Makefile
new file mode 100644
index 0000000..910e94f
--- /dev/null
+++ b/tools/dosfstools/Makefile
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2012-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=dosfstools
+PKG_VERSION:=3.0.27
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/dosfstools/dosfstools/releases/download/v$(PKG_VERSION)/ \
+ http://fossies.org/linux/misc
+PKG_MD5SUM:=2e31e7bdf92998e41ed17de505a4a552
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+ifeq ($(HOST_OS),Darwin)
+LDLIBS += -liconv
+endif
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) SHELL="$(BASH)" LDFLAGS="$(HOST_LDFLAGS)" LDLIBS="$(LDLIBS)"
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/mkfs.fat $(STAGING_DIR_HOST)/bin/
+ $(LN) mkfs.fat $(STAGING_DIR_HOST)/bin/mkdosfs
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mk{dosfs,fs.fat}
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/dosfstools/patches/0001-Add-tags-and-editor-backup-files-to-.gitignore.patch b/tools/dosfstools/patches/0001-Add-tags-and-editor-backup-files-to-.gitignore.patch
new file mode 100644
index 0000000..b0fecdd
--- /dev/null
+++ b/tools/dosfstools/patches/0001-Add-tags-and-editor-backup-files-to-.gitignore.patch
@@ -0,0 +1,25 @@
+From 75c5446d21f02038423d67139a6967975c9b90be Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Sat, 15 Nov 2014 16:48:48 +0100
+Subject: [PATCH 01/14] Add tags and editor backup files to .gitignore
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ .gitignore | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/.gitignore b/.gitignore
+index 384f131..5c9366e 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -2,3 +2,7 @@
+ /fatlabel
+ /fsck.fat
+ /mkfs.fat
++
++tags
++*~
++.*.sw[a-p]
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0002-Fix-indentation-of-fix-power-loss-damage-commit.patch b/tools/dosfstools/patches/0002-Fix-indentation-of-fix-power-loss-damage-commit.patch
new file mode 100644
index 0000000..b12c3b2
--- /dev/null
+++ b/tools/dosfstools/patches/0002-Fix-indentation-of-fix-power-loss-damage-commit.patch
@@ -0,0 +1,100 @@
+From 45aeed0c658cc86e93ae3ae101404e12bec6e102 Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Sun, 16 Nov 2014 19:49:22 +0100
+Subject: [PATCH 02/14] Fix indentation of "fix power loss damage" commit
+
+I fixed the (sometimes misleading) indentation of the code introduced in
+commit 6893c45 to be in line with the reset of the code and also removed
+the /* PATCH ED+DL */ comments which are quite meaningless to the wider
+world.
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ src/check.c | 57 ++++++++++++++++++++++++---------------------------------
+ 1 file changed, 24 insertions(+), 33 deletions(-)
+
+diff --git a/src/check.c b/src/check.c
+index e8aaf92..daa6d69 100644
+--- a/src/check.c
++++ b/src/check.c
+@@ -273,11 +273,10 @@ static int bad_name(DOS_FILE * file)
+ strncmp((const char *)name, "WP ROOT SF", 11) == 0)
+ return 0;
+
+- /* PATCH ED+DL */
+- /* check if we have neither a long filename nor a short name */
+- if ((file->lfn == NULL) && (file->dir_ent.lcase & FAT_NO_83NAME)) {
+- return 1;
+- }
++ /* check if we have neither a long filename nor a short name */
++ if ((file->lfn == NULL) && (file->dir_ent.lcase & FAT_NO_83NAME)) {
++ return 1;
++ }
+
+ /* don't complain about the dummy 11 bytes used by patched Linux
+ kernels */
+@@ -401,20 +400,16 @@ static void auto_rename(DOS_FILE * file)
+ (const char *)file->dir_ent.name, MSDOS_NAME))
+ break;
+ if (!walk) {
+- /* PATCH ED+DL */
+- if(file->dir_ent.lcase & FAT_NO_83NAME)
+- {
+- /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
+- present */
+- file->dir_ent.lcase &= ~FAT_NO_83NAME;
+- /* reset the attributes */
+- file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME); /* only keep the DIR and VOLUME attributes */
+- fs_write(file->offset, MSDOS_NAME+2, file->dir_ent.name);
+- }
+- else
+- {
+- fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
+- }
++ if (file->dir_ent.lcase & FAT_NO_83NAME) {
++ /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
++ present */
++ file->dir_ent.lcase &= ~FAT_NO_83NAME;
++ /* reset the attributes, only keep DIR and VOLUME */
++ file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME);
++ fs_write(file->offset, MSDOS_NAME + 2, file->dir_ent.name);
++ } else {
++ fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
++ }
+ if (file->lfn)
+ lfn_fix_checksum(file->lfn_offset, file->offset,
+ (const char *)file->dir_ent.name);
+@@ -448,20 +443,16 @@ static void rename_file(DOS_FILE * file)
+ walk[1] = 0;
+ for (walk = name; *walk == ' ' || *walk == '\t'; walk++) ;
+ if (file_cvt(walk, file->dir_ent.name)) {
+- /* PATCH ED+DL */
+- if(file->dir_ent.lcase & FAT_NO_83NAME)
+- {
+- /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
+- present */
+- file->dir_ent.lcase &= ~FAT_NO_83NAME;
+- /* reset the attributes */
+- file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME); /* only keep the DIR and VOLUME attributes */
+- fs_write(file->offset, MSDOS_NAME+2, file->dir_ent.name);
+- }
+- else
+- {
+- fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
+- }
++ if (file->dir_ent.lcase & FAT_NO_83NAME) {
++ /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
++ present */
++ file->dir_ent.lcase &= ~FAT_NO_83NAME;
++ /* reset the attributes, only keep DIR and VOLUME */
++ file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME);
++ fs_write(file->offset, MSDOS_NAME + 2, file->dir_ent.name);
++ } else {
++ fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
++ }
+ if (file->lfn)
+ lfn_fix_checksum(file->lfn_offset, file->offset,
+ (const char *)file->dir_ent.name);
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0003-mkfs.fat.c-Use-unsigned-char-for-binary-data.patch b/tools/dosfstools/patches/0003-mkfs.fat.c-Use-unsigned-char-for-binary-data.patch
new file mode 100644
index 0000000..842a7c1
--- /dev/null
+++ b/tools/dosfstools/patches/0003-mkfs.fat.c-Use-unsigned-char-for-binary-data.patch
@@ -0,0 +1,33 @@
+From 8b8948c06de55455b63dc11f765d7ee39f30c4e0 Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Mon, 29 Dec 2014 18:24:54 +0100
+Subject: [PATCH 03/14] mkfs.fat.c: Use unsigned char for binary data
+
+Simple char technically works for the dummy_boot_jump variables, but
+some compiler warning settings would give a warning over a signed char
+overflowing with the values given as initializers.
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ src/mkfs.fat.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index 604b7d0..1f702ad 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -219,9 +219,9 @@ struct msdos_dir_entry {
+ /* The "boot code" we put into the filesystem... it writes a message and
+ tells the user to try again */
+
+-char dummy_boot_jump[3] = { 0xeb, 0x3c, 0x90 };
++unsigned char dummy_boot_jump[3] = { 0xeb, 0x3c, 0x90 };
+
+-char dummy_boot_jump_m68k[2] = { 0x60, 0x1c };
++unsigned char dummy_boot_jump_m68k[2] = { 0x60, 0x1c };
+
+ #define MSG_OFFSET_OFFSET 3
+ char dummy_boot_code[BOOTCODE_SIZE] = "\x0e" /* push cs */
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0004-Make-all-char-that-may-take-literals-const.patch b/tools/dosfstools/patches/0004-Make-all-char-that-may-take-literals-const.patch
new file mode 100644
index 0000000..be553c8
--- /dev/null
+++ b/tools/dosfstools/patches/0004-Make-all-char-that-may-take-literals-const.patch
@@ -0,0 +1,169 @@
+From 16e97e9741a02f6c2c29b3da45b62ac798d76403 Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Wed, 28 Jan 2015 15:07:18 +0100
+Subject: [PATCH 04/14] Make all char* that may take literals const
+
+Every char* variable or function argument that may be given a literal
+string is now made const. Additionally add -Wwrite-strings to CFLAGS to
+enable a warning where const would be missing.
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ Makefile | 2 +-
+ src/boot.c | 4 ++--
+ src/check.c | 2 +-
+ src/common.c | 6 +++---
+ src/common.h | 6 +++---
+ src/mkfs.fat.c | 8 +++++---
+ 6 files changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 81256ef..3cbdb76 100644
+--- a/Makefile
++++ b/Makefile
+@@ -30,7 +30,7 @@ MANDIR = $(PREFIX)/share/man
+ #OPTFLAGS = -O2 -fomit-frame-pointer -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
+ OPTFLAGS = -O2 -fomit-frame-pointer -D_GNU_SOURCE $(shell getconf LFS_CFLAGS)
+ #WARNFLAGS = -Wall -pedantic -std=c99
+-WARNFLAGS = -Wall -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wmissing-prototypes -Wstrict-prototypes
++WARNFLAGS = -Wall -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings
+ DEBUGFLAGS = -g
+ CFLAGS += $(OPTFLAGS) $(WARNFLAGS) $(DEBUGFLAGS)
+
+diff --git a/src/boot.c b/src/boot.c
+index 5b3825c..be7bfb7 100644
+--- a/src/boot.c
++++ b/src/boot.c
+@@ -46,7 +46,7 @@
+
+ static struct {
+ __u8 media;
+- char *descr;
++ const char *descr;
+ } mediabytes[] = {
+ {
+ 0xf0, "5.25\" or 3.5\" HD floppy"}, {
+@@ -64,7 +64,7 @@ static struct {
+ #define GET_UNALIGNED_W(f) \
+ ( (__u16)f[0] | ((__u16)f[1]<<8) )
+
+-static char *get_media_descr(unsigned char media)
++static const char *get_media_descr(unsigned char media)
+ {
+ int i;
+
+diff --git a/src/check.c b/src/check.c
+index daa6d69..488f715 100644
+--- a/src/check.c
++++ b/src/check.c
+@@ -464,7 +464,7 @@ static void rename_file(DOS_FILE * file)
+
+ static int handle_dot(DOS_FS * fs, DOS_FILE * file, int dots)
+ {
+- char *name;
++ const char *name;
+
+ name =
+ strncmp((const char *)file->dir_ent.name, MSDOS_DOT,
+diff --git a/src/common.c b/src/common.c
+index af222a2..9d11193 100644
+--- a/src/common.c
++++ b/src/common.c
+@@ -37,7 +37,7 @@ typedef struct _link {
+ struct _link *next;
+ } LINK;
+
+-void die(char *msg, ...)
++void die(const char *msg, ...)
+ {
+ va_list args;
+
+@@ -48,7 +48,7 @@ void die(char *msg, ...)
+ exit(1);
+ }
+
+-void pdie(char *msg, ...)
++void pdie(const char *msg, ...)
+ {
+ va_list args;
+
+@@ -96,7 +96,7 @@ int min(int a, int b)
+ return a < b ? a : b;
+ }
+
+-char get_key(char *valid, char *prompt)
++char get_key(const char *valid, const char *prompt)
+ {
+ int ch, okay;
+
+diff --git a/src/common.h b/src/common.h
+index 8508602..b127f63 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -25,11 +25,11 @@
+ #ifndef _COMMON_H
+ #define _COMMON_H
+
+-void die(char *msg, ...) __attribute((noreturn));
++void die(const char *msg, ...) __attribute((noreturn));
+
+ /* Displays a prinf-style message and terminates the program. */
+
+-void pdie(char *msg, ...) __attribute((noreturn));
++void pdie(const char *msg, ...) __attribute((noreturn));
+
+ /* Like die, but appends an error message according to the state of errno. */
+
+@@ -50,7 +50,7 @@ int min(int a, int b);
+
+ /* Returns the smaller integer value of a and b. */
+
+-char get_key(char *valid, char *prompt);
++char get_key(const char *valid, const char *prompt);
+
+ /* Displays PROMPT and waits for user input. Only characters in VALID are
+ accepted. Terminates the program on EOF. Returns the character. */
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index 1f702ad..a3dff54 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -250,7 +250,7 @@ char dummy_boot_code[BOOTCODE_SIZE] = "\x0e" /* push cs */
+
+ /* Global variables - the root of all evil :-) - see these and weep! */
+
+-static char *program_name = "mkfs.fat"; /* Name of the program */
++static const char *program_name = "mkfs.fat"; /* Name of the program */
+ static char *device_name = NULL; /* Name of the device on which to create the filesystem */
+ static int atari_format = 0; /* Use Atari variation of MS-DOS FS format */
+ static int check = FALSE; /* Default to no readablity checking */
+@@ -1412,6 +1412,7 @@ int main(int argc, char **argv)
+ int create = 0;
+ uint64_t cblocks = 0;
+ int min_sector_size;
++ int bad_block_count = 0;
+
+ if (argc && *argv) { /* What's the program name? */
+ char *p;
+@@ -1653,16 +1654,17 @@ int main(int argc, char **argv)
+ fprintf(stderr, "Warning: block count mismatch: ");
+ fprintf(stderr, "found %llu but assuming %llu.\n", (unsigned long long)cblocks, (unsigned long long)blocks);
+ }
++ if (*tmp)
++ bad_block_count = 1;
+ } else if (optind == argc - 1) { /* Or use value found */
+ if (create)
+ die("Need intended size with -C.");
+ blocks = cblocks;
+- tmp = "";
+ } else {
+ fprintf(stderr, "No device specified!\n");
+ usage();
+ }
+- if (*tmp) {
++ if (bad_block_count) {
+ printf("Bad block count : %s\n", argv[optind + 1]);
+ usage();
+ }
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0005-mkfs.fat-Allow-0xF0-to-be-specified-as-media-byte.patch b/tools/dosfstools/patches/0005-mkfs.fat-Allow-0xF0-to-be-specified-as-media-byte.patch
new file mode 100644
index 0000000..4d2d26a
--- /dev/null
+++ b/tools/dosfstools/patches/0005-mkfs.fat-Allow-0xF0-to-be-specified-as-media-byte.patch
@@ -0,0 +1,122 @@
+From 266a5fc635135a9ffaa8683da1ec03aae1553b7b Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Fri, 20 Feb 2015 03:19:28 +0100
+Subject: [PATCH 05/14] mkfs.fat: Allow 0xF0 to be specified as media byte
+
+Let the -M option accept 0xF0, which should be the proper descriptor
+byte for 3.5" 1.44 MB and 2.88 MB floppies.
+
+Also split the error reporting for -M between badly formatted and
+invalid numbers.
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ manpages/de/mkfs.fat.de.8 | 4 ++--
+ manpages/en/mkfs.fat.8 | 2 +-
+ manpages/po/de/mkfs.fat.8.po | 6 +++---
+ manpages/pot/mkfs.fat.8.pot | 6 +++---
+ src/mkfs.fat.c | 12 ++++++++----
+ 5 files changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/manpages/de/mkfs.fat.de.8 b/manpages/de/mkfs.fat.de.8
+index 5a6eb1a..2386410 100644
+--- a/manpages/de/mkfs.fat.de.8
++++ b/manpages/de/mkfs.fat.de.8
+@@ -121,8 +121,8 @@ return\-line feed combinations, and tabs have been expanded. If the filename
+ is a hyphen (\-), the text is taken from standard input.
+ .IP "\fB\-M\fP \fIFAT\-media\-type\fP" 4
+ Specify the media type to be stored in the FAT boot sector. This value is
+-usually 0xF8 for hard disks and has a value from 0xF9 to 0xFF for floppies
+-or partitions to be used for floppy emulation.
++usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for
++floppies or partitions to be used for floppy emulation.
+ .IP "\fB\-n\fP \fIvolume\-name\fP" 4
+ Sets the volume name (label) of the filesystem. The volume name can be up to
+ 11 characters long. The default is no label.
+diff --git a/manpages/en/mkfs.fat.8 b/manpages/en/mkfs.fat.8
+index 9dd8115..81bf461 100644
+--- a/manpages/en/mkfs.fat.8
++++ b/manpages/en/mkfs.fat.8
+@@ -58,7 +58,7 @@ Read the bad blocks list from \fIfilename\fR.
+ .IP "\fB\-m\fR \fImessage-file\fR" 4
+ Sets the message the user receives on attempts to boot this filesystem without having properly installed an operating system. The message file must not exceed 418 bytes once line feeds have been converted to carriage return-line feed combinations, and tabs have been expanded. If the filename is a hyphen (-), the text is taken from standard input.
+ .IP "\fB\-M\fR \fIFAT-media-type\fR" 4
+-Specify the media type to be stored in the FAT boot sector. This value is usually 0xF8 for hard disks and has a value from 0xF9 to 0xFF for floppies or partitions to be used for floppy emulation.
++Specify the media type to be stored in the FAT boot sector. This value is usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for floppies or partitions to be used for floppy emulation.
+ .IP "\fB\-n\fR \fIvolume-name\fR" 4
+ Sets the volume name (label) of the filesystem. The volume name can be up to 11 characters long. The default is no label.
+ .IP "\fB\-r\fR \fIroot-dir-entries\fR" 4
+diff --git a/manpages/po/de/mkfs.fat.8.po b/manpages/po/de/mkfs.fat.8.po
+index 2531179..360fe16 100644
+--- a/manpages/po/de/mkfs.fat.8.po
++++ b/manpages/po/de/mkfs.fat.8.po
+@@ -3,7 +3,7 @@
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: dosfstools VERSION\n"
+-"POT-Creation-Date: 2014-11-12 00:52+0100\n"
++"POT-Creation-Date: 2015-02-20 03:31+0100\n"
+ "PO-Revision-Date: 2013-06-06 09:34+0300\n"
+ "Last-Translator: Automatically generated\n"
+ "Language-Team: none\n"
+@@ -354,8 +354,8 @@ msgstr ""
+ #: en/mkfs.fat.8:62
+ msgid ""
+ "Specify the media type to be stored in the FAT boot sector. This value is "
+-"usually 0xF8 for hard disks and has a value from 0xF9 to 0xFF for floppies "
+-"or partitions to be used for floppy emulation."
++"usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for "
++"floppies or partitions to be used for floppy emulation."
+ msgstr ""
+
+ #. type: IP
+diff --git a/manpages/pot/mkfs.fat.8.pot b/manpages/pot/mkfs.fat.8.pot
+index a6106bc..32486ea 100644
+--- a/manpages/pot/mkfs.fat.8.pot
++++ b/manpages/pot/mkfs.fat.8.pot
+@@ -7,7 +7,7 @@
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: dosfstools VERSION\n"
+-"POT-Creation-Date: 2014-11-12 00:52+0100\n"
++"POT-Creation-Date: 2015-02-20 03:31+0100\n"
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+ "Language-Team: LANGUAGE <LL@li.org>\n"
+@@ -357,8 +357,8 @@ msgstr ""
+ #: en/mkfs.fat.8:62
+ msgid ""
+ "Specify the media type to be stored in the FAT boot sector. This value is "
+-"usually 0xF8 for hard disks and has a value from 0xF9 to 0xFF for floppies "
+-"or partitions to be used for floppy emulation."
++"usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for "
++"floppies or partitions to be used for floppy emulation."
+ msgstr ""
+
+ #. type: IP
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index a3dff54..e6f9390 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -1569,10 +1569,14 @@ int main(int argc, char **argv)
+ break;
+
+ case 'M': /* M : FAT Media byte */
+- fat_media_byte = (int) strtol (optarg, &tmp, 0);
+- if (*tmp || fat_media_byte < 248 || fat_media_byte > 255) {
+- printf ("FAT Media byte must be between 0xF8 and 0xFF : %s\n", optarg);
+- usage ();
++ fat_media_byte = (int)strtol(optarg, &tmp, 0);
++ if (*tmp) {
++ printf("Bad number for media descriptor : %s\n", optarg);
++ usage();
++ }
++ if (fat_media_byte != 0xf0 && (fat_media_byte < 0xf8 || fat_media_byte > 0xff)) {
++ printf("FAT Media byte must either be between 0xF8 and 0xFF or be 0xF0 : %s\n", optarg);
++ usage();
+ }
+ break;
+
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0006-fsck.fat-Make-r-option-default.patch b/tools/dosfstools/patches/0006-fsck.fat-Make-r-option-default.patch
new file mode 100644
index 0000000..20e7bde
--- /dev/null
+++ b/tools/dosfstools/patches/0006-fsck.fat-Make-r-option-default.patch
@@ -0,0 +1,603 @@
+From 357ab077198bfa6239fa62fd03a546da959ec756 Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Thu, 19 Feb 2015 21:22:54 +0100
+Subject: [PATCH 06/14] fsck.fat: Make -r option default
+
+Default mode is now to interactively repair with the option to write
+the changes back at the end (like the -r option) instead of the previous
+default mode of interactively correcting but never writing back the
+changes.
+
+The -r option continues to be recognized by fsck.fat.
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ manpages/de/fsck.fat.de.8 | 6 ++--
+ manpages/en/fsck.fat.8 | 5 +--
+ manpages/po/de/fsck.fat.8.po | 76 ++++++++++++++++++++------------------------
+ manpages/pot/fsck.fat.8.pot | 76 ++++++++++++++++++++------------------------
+ src/fsck.fat.c | 6 ++--
+ 5 files changed, 76 insertions(+), 93 deletions(-)
+
+diff --git a/manpages/de/fsck.fat.de.8 b/manpages/de/fsck.fat.de.8
+index 1d96e23..f9d70b8 100644
+--- a/manpages/de/fsck.fat.de.8
++++ b/manpages/de/fsck.fat.de.8
+@@ -123,7 +123,8 @@ anything to the filesystem.
+ Same as (\fB\-a\fP), for compatibility with other *fsck.
+ .IP \fB\-r\fP 4
+ Interactively repair the filesystem. The user is asked for advice whenever
+-there is more than one approach to fix an inconsistency.
++there is more than one approach to fix an inconsistency. This is the default
++mode and the option is only retained for backwards compatibility.
+ .IP \fB\-t\fP 4
+ Mark unreadable clusters as bad.
+ .IP \fB\-u\fP 4
+@@ -143,9 +144,6 @@ Write changes to disk immediately.
+ .IP \fB\-y\fP 4
+ Same as \fB\-a\fP (automatically repair filesystem) for compatibility with other
+ fsck tools.
+-.PP
+-\fBNote:\fP If \fB\-a\fP and \fB\-r\fP are absent, the filesystem is only checked, but
+-not repaired.
+
+ .SH "EXIT STATUS"
+ .IP 0 4
+diff --git a/manpages/en/fsck.fat.8 b/manpages/en/fsck.fat.8
+index 3d95dc8..8c54372 100644
+--- a/manpages/en/fsck.fat.8
++++ b/manpages/en/fsck.fat.8
+@@ -93,8 +93,7 @@ anything to the filesystem.
+ .IP "\fB\-p\fR" 4
+ Same as (\fB\-a\fR), for compatibility with other *fsck.
+ .IP "\fB\-r\fR" 4
+-Interactively repair the filesystem. The user is asked for advice whenever
+-there is more than one approach to fix an inconsistency.
++Interactively repair the filesystem. The user is asked for advice whenever there is more than one approach to fix an inconsistency. This is the default mode and the option is only retained for backwards compatibility.
+ .IP "\fB\-t\fR" 4
+ Mark unreadable clusters as bad.
+ .IP "\fB\-u\fR" 4
+@@ -107,8 +106,6 @@ Perform a verification pass. The filesystem check is repeated after the first ru
+ Write changes to disk immediately.
+ .IP "\fB\-y\fR" 4
+ Same as \fB\-a\fR (automatically repair filesystem) for compatibility with other fsck tools.
+-.PP
+-\fBNote:\fR If \fB\-a\fR and \fB\-r\fR are absent, the filesystem is only checked, but not repaired.
+
+ .SH "EXIT STATUS"
+ .IP "0" 4
+diff --git a/manpages/po/de/fsck.fat.8.po b/manpages/po/de/fsck.fat.8.po
+index 3035906..7ca0bc1 100644
+--- a/manpages/po/de/fsck.fat.8.po
++++ b/manpages/po/de/fsck.fat.8.po
+@@ -3,7 +3,7 @@
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: dosfstools VERSION\n"
+-"POT-Creation-Date: 2014-11-12 00:52+0100\n"
++"POT-Creation-Date: 2015-02-20 20:47+0100\n"
+ "PO-Revision-Date: 2013-06-06 09:34+0300\n"
+ "Last-Translator: Automatically generated\n"
+ "Language-Team: none\n"
+@@ -56,30 +56,30 @@ msgid "OPTIONS"
+ msgstr ""
+
+ #. type: SH
+-#: en/fatlabel.8:41 en/fsck.fat.8:128 en/mkfs.fat.8:78
++#: en/fatlabel.8:41 en/fsck.fat.8:125 en/mkfs.fat.8:78
+ #, no-wrap
+ msgid "SEE ALSO"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fatlabel.8:45 en/fsck.fat.8:132
++#: en/fatlabel.8:45 en/fsck.fat.8:129
+ msgid "B<mkfs.fat>(8)"
+ msgstr ""
+
+ #. type: SH
+-#: en/fatlabel.8:46 en/fsck.fat.8:133 en/mkfs.fat.8:83
++#: en/fatlabel.8:46 en/fsck.fat.8:130 en/mkfs.fat.8:83
+ #, no-wrap
+ msgid "HOMEPAGE"
+ msgstr ""
+
+ #. type: SH
+-#: en/fatlabel.8:49 en/fsck.fat.8:136 en/mkfs.fat.8:86
++#: en/fatlabel.8:49 en/fsck.fat.8:133 en/mkfs.fat.8:86
+ #, no-wrap
+ msgid "AUTHORS"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fatlabel.8:50 en/fsck.fat.8:137 en/mkfs.fat.8:87
++#: en/fatlabel.8:50 en/fsck.fat.8:134 en/mkfs.fat.8:87
+ msgid ""
+ "B<dosfstools> were written by Werner Almesberger E<lt>I<werner."
+ "almesberger@lrc.di.epfl.ch>E<gt>, Roman Hodek E<lt>I<Roman.Hodek@informatik."
+@@ -365,31 +365,32 @@ msgid "B<-r>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:98
++#: en/fsck.fat.8:97
+ msgid ""
+ "Interactively repair the filesystem. The user is asked for advice whenever "
+-"there is more than one approach to fix an inconsistency."
++"there is more than one approach to fix an inconsistency. This is the default "
++"mode and the option is only retained for backwards compatibility."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:98
++#: en/fsck.fat.8:97
+ #, no-wrap
+ msgid "B<-t>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:100
++#: en/fsck.fat.8:99
+ msgid "Mark unreadable clusters as bad."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:100
++#: en/fsck.fat.8:99
+ #, no-wrap
+ msgid "B<-u>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:102
++#: en/fsck.fat.8:101
+ msgid ""
+ "Try to undelete the specified file. B<fsck.fat> tries to allocate a chain of "
+ "contiguous unallocated clusters beginning with the start cluster of the "
+@@ -397,24 +398,24 @@ msgid ""
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:102 en/mkfs.fat.8:72
++#: en/fsck.fat.8:101 en/mkfs.fat.8:72
+ #, no-wrap
+ msgid "B<-v>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:104
++#: en/fsck.fat.8:103
+ msgid "Verbose mode. Generates slightly more output."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:104
++#: en/fsck.fat.8:103
+ #, no-wrap
+ msgid "B<-V>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:106
++#: en/fsck.fat.8:105
+ msgid ""
+ "Perform a verification pass. The filesystem check is repeated after the "
+ "first run. The second pass should never report any fixable errors. It may "
+@@ -424,91 +425,84 @@ msgid ""
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:106
++#: en/fsck.fat.8:105
+ #, no-wrap
+ msgid "B<-w>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:108
++#: en/fsck.fat.8:107
+ msgid "Write changes to disk immediately."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:108
++#: en/fsck.fat.8:107
+ #, no-wrap
+ msgid "B<-y>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:110
++#: en/fsck.fat.8:109
+ msgid ""
+ "Same as B<-a> (automatically repair filesystem) for compatibility with other "
+ "fsck tools."
+ msgstr ""
+
+-#. type: Plain text
+-#: en/fsck.fat.8:112
+-msgid ""
+-"B<Note:> If B<-a> and B<-r> are absent, the filesystem is only checked, but "
+-"not repaired."
+-msgstr ""
+-
+ #. type: SH
+-#: en/fsck.fat.8:113
++#: en/fsck.fat.8:110
+ #, no-wrap
+ msgid "EXIT STATUS"
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:114
++#: en/fsck.fat.8:111
+ #, no-wrap
+ msgid "0"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:116
++#: en/fsck.fat.8:113
+ msgid "No recoverable errors have been detected."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:116
++#: en/fsck.fat.8:113
+ #, no-wrap
+ msgid "1"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:118
++#: en/fsck.fat.8:115
+ msgid ""
+ "Recoverable errors have been detected or B<fsck.fat> has discovered an "
+ "internal inconsistency."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:118
++#: en/fsck.fat.8:115
+ #, no-wrap
+ msgid "2"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:120
++#: en/fsck.fat.8:117
+ msgid "Usage error. B<fsck.fat> did not access the filesystem."
+ msgstr ""
+
+ #. type: SH
+-#: en/fsck.fat.8:121
++#: en/fsck.fat.8:118
+ #, no-wrap
+ msgid "FILES"
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:122
++#: en/fsck.fat.8:119
+ #, no-wrap
+ msgid "fsck0000.rec, fsck0001.rec, ..."
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:124
++#: en/fsck.fat.8:121
+ msgid ""
+ "When recovering from a corrupted filesystem, B<fsck.fat> dumps recovered "
+ "data into files named 'fsckNNNN.rec' in the top level directory of the "
+@@ -516,13 +510,13 @@ msgid ""
+ msgstr ""
+
+ #. type: SH
+-#: en/fsck.fat.8:125 en/mkfs.fat.8:75
++#: en/fsck.fat.8:122 en/mkfs.fat.8:75
+ #, no-wrap
+ msgid "BUGS"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:127
++#: en/fsck.fat.8:124
+ msgid ""
+ "Does not create . and .. files where necessary. Does not remove entirely "
+ "empty directories. Should give more diagnostic messages. Undeleting files "
+@@ -530,12 +524,12 @@ msgid ""
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:130 en/mkfs.fat.8:80
++#: en/fsck.fat.8:127 en/mkfs.fat.8:80
+ msgid "B<fatlabel>(8)"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:135 en/mkfs.fat.8:85
++#: en/fsck.fat.8:132 en/mkfs.fat.8:85
+ msgid ""
+ "More information about B<fsck.fat> and B<dosfstools> can be found at "
+ "E<lt>I<http://daniel-baumann.ch/software/dosfstools/>E<gt>."
+diff --git a/manpages/pot/fsck.fat.8.pot b/manpages/pot/fsck.fat.8.pot
+index e411819..f5ca313 100644
+--- a/manpages/pot/fsck.fat.8.pot
++++ b/manpages/pot/fsck.fat.8.pot
+@@ -7,7 +7,7 @@
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: dosfstools VERSION\n"
+-"POT-Creation-Date: 2014-11-12 00:52+0100\n"
++"POT-Creation-Date: 2015-02-20 20:47+0100\n"
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+ "Language-Team: LANGUAGE <LL@li.org>\n"
+@@ -59,30 +59,30 @@ msgid "OPTIONS"
+ msgstr ""
+
+ #. type: SH
+-#: en/fatlabel.8:41 en/fsck.fat.8:128 en/mkfs.fat.8:78
++#: en/fatlabel.8:41 en/fsck.fat.8:125 en/mkfs.fat.8:78
+ #, no-wrap
+ msgid "SEE ALSO"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fatlabel.8:45 en/fsck.fat.8:132
++#: en/fatlabel.8:45 en/fsck.fat.8:129
+ msgid "B<mkfs.fat>(8)"
+ msgstr ""
+
+ #. type: SH
+-#: en/fatlabel.8:46 en/fsck.fat.8:133 en/mkfs.fat.8:83
++#: en/fatlabel.8:46 en/fsck.fat.8:130 en/mkfs.fat.8:83
+ #, no-wrap
+ msgid "HOMEPAGE"
+ msgstr ""
+
+ #. type: SH
+-#: en/fatlabel.8:49 en/fsck.fat.8:136 en/mkfs.fat.8:86
++#: en/fatlabel.8:49 en/fsck.fat.8:133 en/mkfs.fat.8:86
+ #, no-wrap
+ msgid "AUTHORS"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fatlabel.8:50 en/fsck.fat.8:137 en/mkfs.fat.8:87
++#: en/fatlabel.8:50 en/fsck.fat.8:134 en/mkfs.fat.8:87
+ msgid ""
+ "B<dosfstools> were written by Werner Almesberger E<lt>I<werner."
+ "almesberger@lrc.di.epfl.ch>E<gt>, Roman Hodek E<lt>I<Roman.Hodek@informatik."
+@@ -368,31 +368,32 @@ msgid "B<-r>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:98
++#: en/fsck.fat.8:97
+ msgid ""
+ "Interactively repair the filesystem. The user is asked for advice whenever "
+-"there is more than one approach to fix an inconsistency."
++"there is more than one approach to fix an inconsistency. This is the default "
++"mode and the option is only retained for backwards compatibility."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:98
++#: en/fsck.fat.8:97
+ #, no-wrap
+ msgid "B<-t>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:100
++#: en/fsck.fat.8:99
+ msgid "Mark unreadable clusters as bad."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:100
++#: en/fsck.fat.8:99
+ #, no-wrap
+ msgid "B<-u>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:102
++#: en/fsck.fat.8:101
+ msgid ""
+ "Try to undelete the specified file. B<fsck.fat> tries to allocate a chain of "
+ "contiguous unallocated clusters beginning with the start cluster of the "
+@@ -400,24 +401,24 @@ msgid ""
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:102 en/mkfs.fat.8:72
++#: en/fsck.fat.8:101 en/mkfs.fat.8:72
+ #, no-wrap
+ msgid "B<-v>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:104
++#: en/fsck.fat.8:103
+ msgid "Verbose mode. Generates slightly more output."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:104
++#: en/fsck.fat.8:103
+ #, no-wrap
+ msgid "B<-V>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:106
++#: en/fsck.fat.8:105
+ msgid ""
+ "Perform a verification pass. The filesystem check is repeated after the "
+ "first run. The second pass should never report any fixable errors. It may "
+@@ -427,91 +428,84 @@ msgid ""
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:106
++#: en/fsck.fat.8:105
+ #, no-wrap
+ msgid "B<-w>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:108
++#: en/fsck.fat.8:107
+ msgid "Write changes to disk immediately."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:108
++#: en/fsck.fat.8:107
+ #, no-wrap
+ msgid "B<-y>"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:110
++#: en/fsck.fat.8:109
+ msgid ""
+ "Same as B<-a> (automatically repair filesystem) for compatibility with other "
+ "fsck tools."
+ msgstr ""
+
+-#. type: Plain text
+-#: en/fsck.fat.8:112
+-msgid ""
+-"B<Note:> If B<-a> and B<-r> are absent, the filesystem is only checked, but "
+-"not repaired."
+-msgstr ""
+-
+ #. type: SH
+-#: en/fsck.fat.8:113
++#: en/fsck.fat.8:110
+ #, no-wrap
+ msgid "EXIT STATUS"
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:114
++#: en/fsck.fat.8:111
+ #, no-wrap
+ msgid "0"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:116
++#: en/fsck.fat.8:113
+ msgid "No recoverable errors have been detected."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:116
++#: en/fsck.fat.8:113
+ #, no-wrap
+ msgid "1"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:118
++#: en/fsck.fat.8:115
+ msgid ""
+ "Recoverable errors have been detected or B<fsck.fat> has discovered an "
+ "internal inconsistency."
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:118
++#: en/fsck.fat.8:115
+ #, no-wrap
+ msgid "2"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:120
++#: en/fsck.fat.8:117
+ msgid "Usage error. B<fsck.fat> did not access the filesystem."
+ msgstr ""
+
+ #. type: SH
+-#: en/fsck.fat.8:121
++#: en/fsck.fat.8:118
+ #, no-wrap
+ msgid "FILES"
+ msgstr ""
+
+ #. type: IP
+-#: en/fsck.fat.8:122
++#: en/fsck.fat.8:119
+ #, no-wrap
+ msgid "fsck0000.rec, fsck0001.rec, ..."
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:124
++#: en/fsck.fat.8:121
+ msgid ""
+ "When recovering from a corrupted filesystem, B<fsck.fat> dumps recovered "
+ "data into files named 'fsckNNNN.rec' in the top level directory of the "
+@@ -519,13 +513,13 @@ msgid ""
+ msgstr ""
+
+ #. type: SH
+-#: en/fsck.fat.8:125 en/mkfs.fat.8:75
++#: en/fsck.fat.8:122 en/mkfs.fat.8:75
+ #, no-wrap
+ msgid "BUGS"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:127
++#: en/fsck.fat.8:124
+ msgid ""
+ "Does not create . and .. files where necessary. Does not remove entirely "
+ "empty directories. Should give more diagnostic messages. Undeleting files "
+@@ -533,12 +527,12 @@ msgid ""
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:130 en/mkfs.fat.8:80
++#: en/fsck.fat.8:127 en/mkfs.fat.8:80
+ msgid "B<fatlabel>(8)"
+ msgstr ""
+
+ #. type: Plain text
+-#: en/fsck.fat.8:135 en/mkfs.fat.8:85
++#: en/fsck.fat.8:132 en/mkfs.fat.8:85
+ msgid ""
+ "More information about B<fsck.fat> and B<dosfstools> can be found at "
+ "E<lt>I<http://daniel-baumann.ch/software/dosfstools/>E<gt>."
+diff --git a/src/fsck.fat.c b/src/fsck.fat.c
+index c073d9a..6c7fd87 100644
+--- a/src/fsck.fat.c
++++ b/src/fsck.fat.c
+@@ -108,8 +108,8 @@ int main(int argc, char **argv)
+ uint32_t free_clusters = 0;
+
+ memset(&fs, 0, sizeof(fs));
+- rw = salvage_files = verify = 0;
+- interactive = 1;
++ salvage_files = verify = 0;
++ rw = interactive = 1;
+ check_atari();
+
+ while ((c = getopt(argc, argv, "Aac:d:bflnprtu:vVwy")) != EOF)
+@@ -169,7 +169,7 @@ int main(int argc, char **argv)
+ }
+ set_dos_codepage(-1); /* set default codepage if none was given in command line */
+ if ((test || write_immed) && !rw) {
+- fprintf(stderr, "-t and -w require -a or -r\n");
++ fprintf(stderr, "-t and -w can not be used in read only mode\n");
+ exit(2);
+ }
+ if (optind != argc - 1)
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0007-Makefile-fix-typo-in-uninstall-man.patch b/tools/dosfstools/patches/0007-Makefile-fix-typo-in-uninstall-man.patch
new file mode 100644
index 0000000..9eb8cc6
--- /dev/null
+++ b/tools/dosfstools/patches/0007-Makefile-fix-typo-in-uninstall-man.patch
@@ -0,0 +1,30 @@
+From fb6aea6f5547d59b6e8c287ad8e61854af5a34b0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Thu, 26 Feb 2015 12:50:57 +0100
+Subject: [PATCH 07/14] Makefile: fix typo in uninstall-man
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 3cbdb76..d25510f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -127,7 +127,7 @@ uninstall-man:
+ for MANPAGE in manpages/en/*; \
+ do \
+ SECTION="8"; \
+- rm -f $(DESTDIR)/$(MANDIR}/man$${SECTION}/$$(basename $${MANPAGE} .en.$${SECTION}).$${SECTION}; \
++ rm -f $(DESTDIR)/$(MANDIR)/man$${SECTION}/$$(basename $${MANPAGE} .en.$${SECTION}).$${SECTION}; \
+ done
+
+ for LANGUAGE in $(LANGUAGES); \
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0008-Makefile-avoid-using-install-D.patch b/tools/dosfstools/patches/0008-Makefile-avoid-using-install-D.patch
new file mode 100644
index 0000000..ad59577
--- /dev/null
+++ b/tools/dosfstools/patches/0008-Makefile-avoid-using-install-D.patch
@@ -0,0 +1,43 @@
+From 02b5a6d9a407daebe903fe64fb1b22673aaa7e92 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Thu, 26 Feb 2015 12:51:23 +0100
+Subject: [PATCH 08/14] Makefile: avoid using install -D
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+OS X and FreeBSD are not compatible with this option
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ Makefile | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index d25510f..1593f3d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -62,7 +62,8 @@ install-man:
+ for MANPAGE in manpages/en/*; \
+ do \
+ SECTION="8"; \
+- install -D -m 0644 $${MANPAGE} $(DESTDIR)/$(MANDIR)/man$${SECTION}/$$(basename $${MANPAGE}); \
++ mkdir -p $(DESTDIR)/$(MANDIR)/man$${SECTION}/; \
++ install -m 0644 $${MANPAGE} $(DESTDIR)/$(MANDIR)/man$${SECTION}/$$(basename $${MANPAGE}); \
+ done
+
+ for LANGUAGE in $(LANGUAGES); \
+@@ -70,7 +71,8 @@ install-man:
+ for MANPAGE in manpages/$${LANGUAGE}/*; \
+ do \
+ SECTION="8"; \
+- install -D -m 0644 $${MANPAGE} $(DESTDIR)/$(MANDIR)/$${LANGUAGE}/man$${SECTION}/$$(basename $${MANPAGE} .$${LANGUAGE}.$${SECTION}).$${SECTION}; \
++ mkdir -p $(DESTDIR)/$(MANDIR)/$${LANGUAGE}/man$${SECTION}/; \
++ install -m 0644 $${MANPAGE} $(DESTDIR)/$(MANDIR)/$${LANGUAGE}/man$${SECTION}/$$(basename $${MANPAGE} .$${LANGUAGE}.$${SECTION}).$${SECTION}; \
+ done; \
+ done
+ install-symlinks: install-bin install-man
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0009-Improve-.gitignore.patch b/tools/dosfstools/patches/0009-Improve-.gitignore.patch
new file mode 100644
index 0000000..25d5fe6
--- /dev/null
+++ b/tools/dosfstools/patches/0009-Improve-.gitignore.patch
@@ -0,0 +1,28 @@
+From 628b3ec05b304e77eed05c57457ff7bb39401f6c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Thu, 26 Feb 2015 19:41:19 +0100
+Subject: [PATCH 09/14] Improve .gitignore
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ .gitignore | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/.gitignore b/.gitignore
+index 5c9366e..2dc4ca9 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -6,3 +6,6 @@
+ tags
+ *~
+ .*.sw[a-p]
++*.orig
++*.rej
++*.DS_Store
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0010-Remove-non-standard-int-types.patch b/tools/dosfstools/patches/0010-Remove-non-standard-int-types.patch
new file mode 100644
index 0000000..b3ee2ad
--- /dev/null
+++ b/tools/dosfstools/patches/0010-Remove-non-standard-int-types.patch
@@ -0,0 +1,538 @@
+From 245d0cce5e77d7465d61bfde91bc79477d5e6fd6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Thu, 26 Feb 2015 19:22:54 +0100
+Subject: [PATCH 10/14] Remove non standard int types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ src/boot.c | 16 +++----
+ src/common.h | 2 -
+ src/file.c | 2 -
+ src/fsck.fat.h | 148 ++++++++++++++++++++++++++++-----------------------------
+ src/io.c | 1 -
+ src/lfn.c | 23 ++++-----
+ src/mkfs.fat.c | 95 ++++++++++++++++++------------------
+ 7 files changed, 138 insertions(+), 149 deletions(-)
+
+diff --git a/src/boot.c b/src/boot.c
+index be7bfb7..0c0918f 100644
+--- a/src/boot.c
++++ b/src/boot.c
+@@ -25,8 +25,8 @@
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+ #include <stdio.h>
++#include <stdint.h>
+ #include <string.h>
+-#include <sys/types.h>
+ #include <stdlib.h>
+ #include <time.h>
+
+@@ -45,7 +45,7 @@
+ #define FAT16_THRESHOLD 65525
+
+ static struct {
+- __u8 media;
++ uint8_t media;
+ const char *descr;
+ } mediabytes[] = {
+ {
+@@ -62,7 +62,7 @@ static struct {
+
+ /* Unaligned fields must first be accessed byte-wise */
+ #define GET_UNALIGNED_W(f) \
+- ( (__u16)f[0] | ((__u16)f[1]<<8) )
++ ( (uint16_t)f[0] | ((uint16_t)f[1]<<8) )
+
+ static const char *get_media_descr(unsigned char media)
+ {
+@@ -166,18 +166,18 @@ static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, int lss)
+ fs_read(fs->backupboot_start, sizeof(b2), &b2);
+ if (memcmp(b, &b2, sizeof(b2)) != 0) {
+ /* there are any differences */
+- __u8 *p, *q;
++ uint8_t *p, *q;
+ int i, pos, first = 1;
+ char buf[20];
+
+ printf("There are differences between boot sector and its backup.\n");
+ printf("This is mostly harmless. Differences: (offset:original/backup)\n ");
+ pos = 2;
+- for (p = (__u8 *) b, q = (__u8 *) & b2, i = 0; i < sizeof(b2);
++ for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i < sizeof(b2);
+ ++p, ++q, ++i) {
+ if (*p != *q) {
+ sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ",
+- (unsigned)(p - (__u8 *) b), *p, *q);
++ (unsigned)(p - (uint8_t *) b), *p, *q);
+ if (pos + strlen(buf) > 78)
+ printf("\n "), pos = 2;
+ printf("%s", buf);
+@@ -227,7 +227,7 @@ static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, int lss)
+ if (interactive && get_key("12", "?") == '1') {
+ /* search for a free reserved sector (not boot sector and not
+ * backup boot sector) */
+- __u32 s;
++ uint32_t s;
+ for (s = 1; s < le16toh(b->reserved); ++s)
+ if (s != le16toh(b->backup_boot))
+ break;
+@@ -425,7 +425,7 @@ void read_boot(DOS_FS * fs)
+ fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
+ fs->fat_size = fat_length * logical_sector_size;
+
+- fs->label = calloc(12, sizeof(__u8));
++ fs->label = calloc(12, sizeof(uint8_t));
+ if (fs->fat_bits == 12 || fs->fat_bits == 16) {
+ struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
+ if (b16->extended_sig == 0x29)
+diff --git a/src/common.h b/src/common.h
+index b127f63..c15efb5 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -20,8 +20,6 @@
+ can be found in /usr/share/common-licenses/GPL-3 file.
+ */
+
+-#include <asm/types.h>
+-
+ #ifndef _COMMON_H
+ #define _COMMON_H
+
+diff --git a/src/file.c b/src/file.c
+index 30adcde..0b53840 100644
+--- a/src/file.c
++++ b/src/file.c
+@@ -34,8 +34,6 @@
+ #define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h> */
+ #define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
+
+-#include <asm/types.h>
+-
+ #include <linux/msdos_fs.h>
+
+ #include "common.h"
+diff --git a/src/fsck.fat.h b/src/fsck.fat.h
+index e5ade5b..27e9d52 100644
+--- a/src/fsck.fat.h
++++ b/src/fsck.fat.h
+@@ -28,14 +28,10 @@
+ #define _DOSFSCK_H
+
+ #include <fcntl.h>
+-#include <sys/types.h>
+ #define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
+ #define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h> */
+ #define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
+
+-#include <asm/types.h>
+-#include <asm/byteorder.h>
+-
+ #include <linux/msdos_fs.h>
+
+ #include <stddef.h>
+@@ -49,95 +45,95 @@
+ /* ++roman: Use own definition of boot sector structure -- the kernel headers'
+ * name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */
+ struct boot_sector {
+- __u8 ignored[3]; /* Boot strap short or near jump */
+- __u8 system_id[8]; /* Name - can be used to special case
++ uint8_t ignored[3]; /* Boot strap short or near jump */
++ uint8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+- __u8 sector_size[2]; /* bytes per logical sector */
+- __u8 cluster_size; /* sectors/cluster */
+- __u16 reserved; /* reserved sectors */
+- __u8 fats; /* number of FATs */
+- __u8 dir_entries[2]; /* root directory entries */
+- __u8 sectors[2]; /* number of sectors */
+- __u8 media; /* media code (unused) */
+- __u16 fat_length; /* sectors/FAT */
+- __u16 secs_track; /* sectors per track */
+- __u16 heads; /* number of heads */
+- __u32 hidden; /* hidden sectors (unused) */
+- __u32 total_sect; /* number of sectors (if sectors == 0) */
++ uint8_t sector_size[2]; /* bytes per logical sector */
++ uint8_t cluster_size; /* sectors/cluster */
++ uint16_t reserved; /* reserved sectors */
++ uint8_t fats; /* number of FATs */
++ uint8_t dir_entries[2]; /* root directory entries */
++ uint8_t sectors[2]; /* number of sectors */
++ uint8_t media; /* media code (unused) */
++ uint16_t fat_length; /* sectors/FAT */
++ uint16_t secs_track; /* sectors per track */
++ uint16_t heads; /* number of heads */
++ uint32_t hidden; /* hidden sectors (unused) */
++ uint32_t total_sect; /* number of sectors (if sectors == 0) */
+
+ /* The following fields are only used by FAT32 */
+- __u32 fat32_length; /* sectors/FAT */
+- __u16 flags; /* bit 8: fat mirroring, low 4: active fat */
+- __u8 version[2]; /* major, minor filesystem version */
+- __u32 root_cluster; /* first cluster in root directory */
+- __u16 info_sector; /* filesystem info sector */
+- __u16 backup_boot; /* backup boot sector */
+- __u8 reserved2[12]; /* Unused */
+-
+- __u8 drive_number; /* Logical Drive Number */
+- __u8 reserved3; /* Unused */
+-
+- __u8 extended_sig; /* Extended Signature (0x29) */
+- __u32 serial; /* Serial number */
+- __u8 label[11]; /* FS label */
+- __u8 fs_type[8]; /* FS Type */
++ uint32_t fat32_length; /* sectors/FAT */
++ uint16_t flags; /* bit 8: fat mirroring, low 4: active fat */
++ uint8_t version[2]; /* major, minor filesystem version */
++ uint32_t root_cluster; /* first cluster in root directory */
++ uint16_t info_sector; /* filesystem info sector */
++ uint16_t backup_boot; /* backup boot sector */
++ uint8_t reserved2[12]; /* Unused */
++
++ uint8_t drive_number; /* Logical Drive Number */
++ uint8_t reserved3; /* Unused */
++
++ uint8_t extended_sig; /* Extended Signature (0x29) */
++ uint32_t serial; /* Serial number */
++ uint8_t label[11]; /* FS label */
++ uint8_t fs_type[8]; /* FS Type */
+
+ /* fill up to 512 bytes */
+- __u8 junk[422];
++ uint8_t junk[422];
+ } __attribute__ ((packed));
+
+ struct boot_sector_16 {
+- __u8 ignored[3]; /* Boot strap short or near jump */
+- __u8 system_id[8]; /* Name - can be used to special case
++ uint8_t ignored[3]; /* Boot strap short or near jump */
++ uint8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+- __u8 sector_size[2]; /* bytes per logical sector */
+- __u8 cluster_size; /* sectors/cluster */
+- __u16 reserved; /* reserved sectors */
+- __u8 fats; /* number of FATs */
+- __u8 dir_entries[2]; /* root directory entries */
+- __u8 sectors[2]; /* number of sectors */
+- __u8 media; /* media code (unused) */
+- __u16 fat_length; /* sectors/FAT */
+- __u16 secs_track; /* sectors per track */
+- __u16 heads; /* number of heads */
+- __u32 hidden; /* hidden sectors (unused) */
+- __u32 total_sect; /* number of sectors (if sectors == 0) */
+-
+- __u8 drive_number; /* Logical Drive Number */
+- __u8 reserved2; /* Unused */
+-
+- __u8 extended_sig; /* Extended Signature (0x29) */
+- __u32 serial; /* Serial number */
+- __u8 label[11]; /* FS label */
+- __u8 fs_type[8]; /* FS Type */
++ uint8_t sector_size[2]; /* bytes per logical sector */
++ uint8_t cluster_size; /* sectors/cluster */
++ uint16_t reserved; /* reserved sectors */
++ uint8_t fats; /* number of FATs */
++ uint8_t dir_entries[2]; /* root directory entries */
++ uint8_t sectors[2]; /* number of sectors */
++ uint8_t media; /* media code (unused) */
++ uint16_t fat_length; /* sectors/FAT */
++ uint16_t secs_track; /* sectors per track */
++ uint16_t heads; /* number of heads */
++ uint32_t hidden; /* hidden sectors (unused) */
++ uint32_t total_sect; /* number of sectors (if sectors == 0) */
++
++ uint8_t drive_number; /* Logical Drive Number */
++ uint8_t reserved2; /* Unused */
++
++ uint8_t extended_sig; /* Extended Signature (0x29) */
++ uint32_t serial; /* Serial number */
++ uint8_t label[11]; /* FS label */
++ uint8_t fs_type[8]; /* FS Type */
+
+ /* fill up to 512 bytes */
+- __u8 junk[450];
++ uint8_t junk[450];
+ } __attribute__ ((packed));
+
+ struct info_sector {
+- __u32 magic; /* Magic for info sector ('RRaA') */
+- __u8 junk[0x1dc];
+- __u32 reserved1; /* Nothing as far as I can tell */
+- __u32 signature; /* 0x61417272 ('rrAa') */
+- __u32 free_clusters; /* Free cluster count. -1 if unknown */
+- __u32 next_cluster; /* Most recently allocated cluster. */
+- __u32 reserved2[3];
+- __u16 reserved3;
+- __u16 boot_sign;
++ uint32_t magic; /* Magic for info sector ('RRaA') */
++ uint8_t junk[0x1dc];
++ uint32_t reserved1; /* Nothing as far as I can tell */
++ uint32_t signature; /* 0x61417272 ('rrAa') */
++ uint32_t free_clusters; /* Free cluster count. -1 if unknown */
++ uint32_t next_cluster; /* Most recently allocated cluster. */
++ uint32_t reserved2[3];
++ uint16_t reserved3;
++ uint16_t boot_sign;
+ };
+
+ typedef struct {
+- __u8 name[8], ext[3]; /* name and extension */
+- __u8 attr; /* attribute bits */
+- __u8 lcase; /* Case for base and extension */
+- __u8 ctime_ms; /* Creation time, milliseconds */
+- __u16 ctime; /* Creation time */
+- __u16 cdate; /* Creation date */
+- __u16 adate; /* Last access date */
+- __u16 starthi; /* High 16 bits of cluster in FAT32 */
+- __u16 time, date, start; /* time, date and first cluster */
+- __u32 size; /* file size (in bytes) */
++ uint8_t name[8], ext[3]; /* name and extension */
++ uint8_t attr; /* attribute bits */
++ uint8_t lcase; /* Case for base and extension */
++ uint8_t ctime_ms; /* Creation time, milliseconds */
++ uint16_t ctime; /* Creation time */
++ uint16_t cdate; /* Creation date */
++ uint16_t adate; /* Last access date */
++ uint16_t starthi; /* High 16 bits of cluster in FAT32 */
++ uint16_t time, date, start; /* time, date and first cluster */
++ uint32_t size; /* file size (in bytes) */
+ } __attribute__ ((packed)) DIR_ENT;
+
+ typedef struct _dos_file {
+diff --git a/src/io.c b/src/io.c
+index 3755ba5..450432c 100644
+--- a/src/io.c
++++ b/src/io.c
+@@ -31,7 +31,6 @@
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+ #define _LARGEFILE64_SOURCE
+-#include <sys/types.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+diff --git a/src/lfn.c b/src/lfn.c
+index 2e60198..2601172 100644
+--- a/src/lfn.c
++++ b/src/lfn.c
+@@ -21,6 +21,7 @@
+ */
+
+ #include <stdio.h>
++#include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <limits.h>
+@@ -33,14 +34,14 @@
+ #include "file.h"
+
+ typedef struct {
+- __u8 id; /* sequence number for slot */
+- __u8 name0_4[10]; /* first 5 characters in name */
+- __u8 attr; /* attribute byte */
+- __u8 reserved; /* always 0 */
+- __u8 alias_checksum; /* checksum for 8.3 alias */
+- __u8 name5_10[12]; /* 6 more characters in name */
+- __u16 start; /* starting cluster number, 0 in long slots */
+- __u8 name11_12[4]; /* last 2 characters in name */
++ uint8_t id; /* sequence number for slot */
++ uint8_t name0_4[10]; /* first 5 characters in name */
++ uint8_t attr; /* attribute byte */
++ uint8_t reserved; /* always 0 */
++ uint8_t alias_checksum; /* checksum for 8.3 alias */
++ uint8_t name5_10[12]; /* 6 more characters in name */
++ uint16_t start; /* starting cluster number, 0 in long slots */
++ uint8_t name11_12[4]; /* last 2 characters in name */
+ } LFN_ENT;
+
+ #define LFN_ID_START 0x40
+@@ -173,7 +174,7 @@ static void clear_lfn_slots(int start, int end)
+ void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name)
+ {
+ int i;
+- __u8 sum;
++ uint8_t sum;
+ for (sum = 0, i = 0; i < 11; i++)
+ sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + short_name[i];
+
+@@ -409,7 +410,7 @@ void lfn_add_slot(DIR_ENT * de, loff_t dir_offset)
+ char *lfn_get(DIR_ENT * de, loff_t * lfn_offset)
+ {
+ char *lfn;
+- __u8 sum;
++ uint8_t sum;
+ int i;
+
+ *lfn_offset = 0;
+@@ -453,7 +454,7 @@ char *lfn_get(DIR_ENT * de, loff_t * lfn_offset)
+ return NULL;
+ case '3':
+ for (i = 0; i < lfn_parts; ++i) {
+- __u8 id = (lfn_parts - i) | (i == 0 ? LFN_ID_START : 0);
++ uint8_t id = (lfn_parts - i) | (i == 0 ? LFN_ID_START : 0);
+ fs_write(lfn_offsets[i] + offsetof(LFN_ENT, id),
+ sizeof(id), &id);
+ }
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index e6f9390..3d1512f 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -60,7 +60,6 @@
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
+-#include <sys/types.h>
+ #include <unistd.h>
+ #include <time.h>
+ #include <errno.h>
+@@ -68,8 +67,6 @@
+ #include <stdint.h>
+ #include <endian.h>
+
+-#include <asm/types.h>
+-
+ /* In earlier versions, an own llseek() was used, but glibc lseek() is
+ * sufficient (or even better :) for 64 bit offsets in the meantime */
+ #define llseek lseek
+@@ -148,72 +145,72 @@ static inline int cdiv(int a, int b)
+ * alignments */
+
+ struct msdos_volume_info {
+- __u8 drive_number; /* BIOS drive number */
+- __u8 RESERVED; /* Unused */
+- __u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
+- __u8 volume_id[4]; /* Volume ID number */
+- __u8 volume_label[11]; /* Volume label */
+- __u8 fs_type[8]; /* Typically FAT12 or FAT16 */
++ uint8_t drive_number; /* BIOS drive number */
++ uint8_t RESERVED; /* Unused */
++ uint8_t ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
++ uint8_t volume_id[4]; /* Volume ID number */
++ uint8_t volume_label[11]; /* Volume label */
++ uint8_t fs_type[8]; /* Typically FAT12 or FAT16 */
+ } __attribute__ ((packed));
+
+ struct msdos_boot_sector {
+- __u8 boot_jump[3]; /* Boot strap short or near jump */
+- __u8 system_id[8]; /* Name - can be used to special case
++ uint8_t boot_jump[3]; /* Boot strap short or near jump */
++ uint8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+- __u8 sector_size[2]; /* bytes per logical sector */
+- __u8 cluster_size; /* sectors/cluster */
+- __u16 reserved; /* reserved sectors */
+- __u8 fats; /* number of FATs */
+- __u8 dir_entries[2]; /* root directory entries */
+- __u8 sectors[2]; /* number of sectors */
+- __u8 media; /* media code (unused) */
+- __u16 fat_length; /* sectors/FAT */
+- __u16 secs_track; /* sectors per track */
+- __u16 heads; /* number of heads */
+- __u32 hidden; /* hidden sectors (unused) */
+- __u32 total_sect; /* number of sectors (if sectors == 0) */
++ uint8_t sector_size[2]; /* bytes per logical sector */
++ uint8_t cluster_size; /* sectors/cluster */
++ uint16_t reserved; /* reserved sectors */
++ uint8_t fats; /* number of FATs */
++ uint8_t dir_entries[2]; /* root directory entries */
++ uint8_t sectors[2]; /* number of sectors */
++ uint8_t media; /* media code (unused) */
++ uint16_t fat_length; /* sectors/FAT */
++ uint16_t secs_track; /* sectors per track */
++ uint16_t heads; /* number of heads */
++ uint32_t hidden; /* hidden sectors (unused) */
++ uint32_t total_sect; /* number of sectors (if sectors == 0) */
+ union {
+ struct {
+ struct msdos_volume_info vi;
+- __u8 boot_code[BOOTCODE_SIZE];
++ uint8_t boot_code[BOOTCODE_SIZE];
+ } __attribute__ ((packed)) _oldfat;
+ struct {
+- __u32 fat32_length; /* sectors/FAT */
+- __u16 flags; /* bit 8: fat mirroring, low 4: active fat */
+- __u8 version[2]; /* major, minor filesystem version */
+- __u32 root_cluster; /* first cluster in root directory */
+- __u16 info_sector; /* filesystem info sector */
+- __u16 backup_boot; /* backup boot sector */
+- __u16 reserved2[6]; /* Unused */
++ uint32_t fat32_length; /* sectors/FAT */
++ uint16_t flags; /* bit 8: fat mirroring, low 4: active fat */
++ uint8_t version[2]; /* major, minor filesystem version */
++ uint32_t root_cluster; /* first cluster in root directory */
++ uint16_t info_sector; /* filesystem info sector */
++ uint16_t backup_boot; /* backup boot sector */
++ uint16_t reserved2[6]; /* Unused */
+ struct msdos_volume_info vi;
+- __u8 boot_code[BOOTCODE_FAT32_SIZE];
++ uint8_t boot_code[BOOTCODE_FAT32_SIZE];
+ } __attribute__ ((packed)) _fat32;
+ } __attribute__ ((packed)) fstype;
+- __u16 boot_sign;
++ uint16_t boot_sign;
+ } __attribute__ ((packed));
+ #define fat32 fstype._fat32
+ #define oldfat fstype._oldfat
+
+ struct fat32_fsinfo {
+- __u32 reserved1; /* Nothing as far as I can tell */
+- __u32 signature; /* 0x61417272L */
+- __u32 free_clusters; /* Free cluster count. -1 if unknown */
+- __u32 next_cluster; /* Most recently allocated cluster.
++ uint32_t reserved1; /* Nothing as far as I can tell */
++ uint32_t signature; /* 0x61417272L */
++ uint32_t free_clusters; /* Free cluster count. -1 if unknown */
++ uint32_t next_cluster; /* Most recently allocated cluster.
+ * Unused under Linux. */
+- __u32 reserved2[4];
++ uint32_t reserved2[4];
+ };
+
+ struct msdos_dir_entry {
+ char name[8], ext[3]; /* name and extension */
+- __u8 attr; /* attribute bits */
+- __u8 lcase; /* Case for base and extension */
+- __u8 ctime_ms; /* Creation time, milliseconds */
+- __u16 ctime; /* Creation time */
+- __u16 cdate; /* Creation date */
+- __u16 adate; /* Last access date */
+- __u16 starthi; /* high 16 bits of first cl. (FAT32) */
+- __u16 time, date, start; /* time, date and first cluster */
+- __u32 size; /* file size (in bytes) */
++ uint8_t attr; /* attribute bits */
++ uint8_t lcase; /* Case for base and extension */
++ uint8_t ctime_ms; /* Creation time, milliseconds */
++ uint16_t ctime; /* Creation time */
++ uint16_t cdate; /* Creation date */
++ uint16_t adate; /* Last access date */
++ uint16_t starthi; /* high 16 bits of first cl. (FAT32) */
++ uint16_t time, date, start; /* time, date and first cluster */
++ uint32_t size; /* file size (in bytes) */
+ } __attribute__ ((packed));
+
+ /* The "boot code" we put into the filesystem... it writes a message and
+@@ -826,7 +823,7 @@ static void setup_tables(void)
+ bs.hidden = htole32(hidden_sectors);
+ else {
+ /* In Atari format, hidden is a 16 bit field */
+- __u16 hidden = htole16(hidden_sectors);
++ uint16_t hidden = htole16(hidden_sectors);
+ if (hidden_sectors & ~0xffff)
+ die("#hidden doesn't fit in 16bit field of Atari format\n");
+ memcpy(&bs.hidden, &hidden, 2);
+@@ -1279,7 +1276,7 @@ static void setup_tables(void)
+ info->next_cluster = htole32(2);
+
+ /* Info sector also must have boot sign */
+- *(__u16 *) (info_sector + 0x1fe) = htole16(BOOT_SIGN);
++ *(uint16_t *) (info_sector + 0x1fe) = htole16(BOOT_SIGN);
+ }
+
+ if (!(blank_sector = malloc(sector_size)))
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0011-Remove-linux-msdos_fs.h-includes.patch b/tools/dosfstools/patches/0011-Remove-linux-msdos_fs.h-includes.patch
new file mode 100644
index 0000000..08bd36d
--- /dev/null
+++ b/tools/dosfstools/patches/0011-Remove-linux-msdos_fs.h-includes.patch
@@ -0,0 +1,209 @@
+From e18d72f70e30109492e9602ace5560e0c90b4a8b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Sat, 7 Mar 2015 13:23:23 +0100
+Subject: [PATCH 11/14] Remove linux/msdos_fs.h includes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ src/file.c | 7 +------
+ src/file.h | 2 ++
+ src/fsck.fat.h | 8 ++------
+ src/mkfs.fat.c | 32 +++---------------------------
+ src/msdos_fs.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 69 insertions(+), 41 deletions(-)
+ create mode 100644 src/msdos_fs.h
+
+diff --git a/src/file.c b/src/file.c
+index 0b53840..9519070 100644
+--- a/src/file.c
++++ b/src/file.c
+@@ -30,14 +30,9 @@
+ #include <ctype.h>
+ #include <unistd.h>
+
+-#define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
+-#define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h> */
+-#define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
+-
+-#include <linux/msdos_fs.h>
+-
+ #include "common.h"
+ #include "file.h"
++#include "msdos_fs.h"
+ #include "charconv.h"
+
+ FDSC *fp_root = NULL;
+diff --git a/src/file.h b/src/file.h
+index 3adfc96..eaaf356 100644
+--- a/src/file.h
++++ b/src/file.h
+@@ -23,6 +23,8 @@
+ #ifndef _FILE_H
+ #define _FILE_H
+
++#include "msdos_fs.h"
++
+ typedef enum { fdt_none, fdt_drop, fdt_undelete } FD_TYPE;
+
+ typedef struct _fptr {
+diff --git a/src/fsck.fat.h b/src/fsck.fat.h
+index 27e9d52..e5f6178 100644
+--- a/src/fsck.fat.h
++++ b/src/fsck.fat.h
+@@ -28,16 +28,12 @@
+ #define _DOSFSCK_H
+
+ #include <fcntl.h>
+-#define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
+-#define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h> */
+-#define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
+-
+-#include <linux/msdos_fs.h>
+-
+ #include <stddef.h>
+ #include <stdint.h>
+ #include <endian.h>
+
++#include "msdos_fs.h"
++
+ #define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+
+ #define FAT_STATE_DIRTY 0x01
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index 3d1512f..76d40d8 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -67,6 +67,8 @@
+ #include <stdint.h>
+ #include <endian.h>
+
++#include "msdos_fs.h"
++
+ /* In earlier versions, an own llseek() was used, but glibc lseek() is
+ * sufficient (or even better :) for 64 bit offsets in the meantime */
+ #define llseek lseek
+@@ -99,21 +101,6 @@ static inline int cdiv(int a, int b)
+ return (a + b - 1) / b;
+ }
+
+-/* MS-DOS filesystem structures -- I included them here instead of
+- including linux/msdos_fs.h since that doesn't include some fields we
+- need */
+-
+-#define ATTR_RO 1 /* read-only */
+-#define ATTR_HIDDEN 2 /* hidden */
+-#define ATTR_SYS 4 /* system */
+-#define ATTR_VOLUME 8 /* volume label */
+-#define ATTR_DIR 16 /* directory */
+-#define ATTR_ARCH 32 /* archived */
+-
+-#define ATTR_NONE 0 /* no attribute bits */
+-#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
+- /* attribute bits that are copied "as is" */
+-
+ /* FAT values */
+ #define FAT_EOF (atari_format ? 0x0fffffff : 0x0ffffff8)
+ #define FAT_BAD 0x0ffffff7
+@@ -200,19 +187,6 @@ struct fat32_fsinfo {
+ uint32_t reserved2[4];
+ };
+
+-struct msdos_dir_entry {
+- char name[8], ext[3]; /* name and extension */
+- uint8_t attr; /* attribute bits */
+- uint8_t lcase; /* Case for base and extension */
+- uint8_t ctime_ms; /* Creation time, milliseconds */
+- uint16_t ctime; /* Creation time */
+- uint16_t cdate; /* Creation date */
+- uint16_t adate; /* Last access date */
+- uint16_t starthi; /* high 16 bits of first cl. (FAT32) */
+- uint16_t time, date, start; /* time, date and first cluster */
+- uint32_t size; /* file size (in bytes) */
+-} __attribute__ ((packed));
+-
+ /* The "boot code" we put into the filesystem... it writes a message and
+ tells the user to try again */
+
+@@ -1244,7 +1218,7 @@ static void setup_tables(void)
+ htole16((unsigned short)(ctime->tm_mday +
+ ((ctime->tm_mon + 1) << 5) +
+ ((ctime->tm_year - 80) << 9)));
+- de->ctime_ms = 0;
++ de->ctime_cs = 0;
+ de->ctime = de->time;
+ de->cdate = de->date;
+ de->adate = de->date;
+diff --git a/src/msdos_fs.h b/src/msdos_fs.h
+new file mode 100644
+index 0000000..54b2a34
+--- /dev/null
++++ b/src/msdos_fs.h
+@@ -0,0 +1,61 @@
++/* msdos_fs.h - MS-DOS filesystem constants/structures
++
++ 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.
++
++ 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, see <http://www.gnu.org/licenses/>.
++
++ The complete text of the GNU General Public License
++ can be found in /usr/share/common-licenses/GPL-3 file.
++*/
++
++#ifndef _MSDOS_FS_H
++#define _MSDOS_FS_H
++
++#include <stdint.h>
++
++#define SECTOR_SIZE 512 /* sector size (bytes) */
++#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry))
++#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */
++#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */
++
++#define ATTR_NONE 0 /* no attribute bits */
++#define ATTR_RO 1 /* read-only */
++#define ATTR_HIDDEN 2 /* hidden */
++#define ATTR_SYS 4 /* system */
++#define ATTR_VOLUME 8 /* volume label */
++#define ATTR_DIR 16 /* directory */
++#define ATTR_ARCH 32 /* archived */
++
++/* attribute bits that are copied "as is" */
++#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
++
++#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
++#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG)
++
++#define MSDOS_NAME 11 /* maximum name length */
++#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
++#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
++
++struct msdos_dir_entry {
++ uint8_t name[8], ext[3]; /* name and extension */
++ uint8_t attr; /* attribute bits */
++ uint8_t lcase; /* Case for base and extension */
++ uint8_t ctime_cs; /* Creation time, centiseconds (0-199) */
++ uint16_t ctime; /* Creation time */
++ uint16_t cdate; /* Creation date */
++ uint16_t adate; /* Last access date */
++ uint16_t starthi; /* High 16 bits of cluster in FAT32 */
++ uint16_t time, date, start; /* time, date and first cluster */
++ uint32_t size; /* file size (in bytes) */
++} __attribute__ ((packed));
++
++#endif /* _MSDOS_FS_H */
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0012-fsck.fat-Fix-read-beyond-end-of-array-on-FAT12.patch b/tools/dosfstools/patches/0012-fsck.fat-Fix-read-beyond-end-of-array-on-FAT12.patch
new file mode 100644
index 0000000..cfc5db5
--- /dev/null
+++ b/tools/dosfstools/patches/0012-fsck.fat-Fix-read-beyond-end-of-array-on-FAT12.patch
@@ -0,0 +1,54 @@
+From a41fc323f2ef38f884954a4ba3773a296fd809f8 Mon Sep 17 00:00:00 2001
+From: Andreas Bombe <aeb@debian.org>
+Date: Wed, 11 Mar 2015 21:45:04 +0100
+Subject: [PATCH 12/14] fsck.fat: Fix read beyond end of array on FAT12
+
+When a FAT12 filesystem contains an odd number of clusters, setting the
+last cluster with set_fat() will trigger a read of the next entry,
+which does not exist in the fat array allocated for this.
+
+Round up the allocation to an even number of FAT entries for FAT12 so
+that this is fixed without introducing special casing in get_fat().
+
+Signed-off-by: Andreas Bombe <aeb@debian.org>
+---
+ src/fat.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/src/fat.c b/src/fat.c
+index 027c586..5a92f56 100644
+--- a/src/fat.c
++++ b/src/fat.c
+@@ -80,7 +80,7 @@ void get_fat(FAT_ENTRY * entry, void *fat, uint32_t cluster, DOS_FS * fs)
+ */
+ void read_fat(DOS_FS * fs)
+ {
+- int eff_size;
++ int eff_size, alloc_size;
+ uint32_t i;
+ void *first, *second = NULL;
+ int first_ok, second_ok;
+@@ -96,10 +96,18 @@ void read_fat(DOS_FS * fs)
+
+ total_num_clusters = fs->clusters + 2UL;
+ eff_size = (total_num_clusters * fs->fat_bits + 7) / 8ULL;
+- first = alloc(eff_size);
++
++ if (fs->fat_bits != 12)
++ alloc_size = eff_size;
++ else
++ /* round up to an even number of FAT entries to avoid special
++ * casing the last entry in get_fat() */
++ alloc_size = (total_num_clusters * 12 + 23) / 24 * 3;
++
++ first = alloc(alloc_size);
+ fs_read(fs->fat_start, eff_size, first);
+ if (fs->nfats > 1) {
+- second = alloc(eff_size);
++ second = alloc(alloc_size);
+ fs_read(fs->fat_start + fs->fat_size, eff_size, second);
+ }
+ if (second && memcmp(first, second, eff_size) != 0) {
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0013-Add-compatible-ioctl-calls-for-OSX-and-FreeBSD.patch b/tools/dosfstools/patches/0013-Add-compatible-ioctl-calls-for-OSX-and-FreeBSD.patch
new file mode 100644
index 0000000..244e4f4
--- /dev/null
+++ b/tools/dosfstools/patches/0013-Add-compatible-ioctl-calls-for-OSX-and-FreeBSD.patch
@@ -0,0 +1,217 @@
+From 50897e9d43f61b4ab238d3ebff62cc45d505206a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Sat, 7 Mar 2015 15:55:32 +0100
+Subject: [PATCH 13/14] Add compatible ioctl calls for OSX and FreeBSD
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ src/io.c | 2 --
+ src/mkfs.fat.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 96 insertions(+), 7 deletions(-)
+
+diff --git a/src/io.c b/src/io.c
+index 450432c..7d0d49a 100644
+--- a/src/io.c
++++ b/src/io.c
+@@ -36,10 +36,8 @@
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/stat.h>
+-#include <sys/ioctl.h>
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <linux/fd.h>
+
+ #include "fsck.fat.h"
+ #include "common.h"
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index 76d40d8..02e0918 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -47,17 +47,13 @@
+ #include "version.h"
+
+ #include <fcntl.h>
+-#include <linux/hdreg.h>
+ #include <sys/mount.h>
+-#include <linux/fs.h>
+-#include <linux/fd.h>
+ #include <endian.h>
+ #include <mntent.h>
+ #include <signal.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
+ #include <unistd.h>
+@@ -67,6 +63,40 @@
+ #include <stdint.h>
+ #include <endian.h>
+
++#if defined(__linux__)
++ #include <linux/hdreg.h>
++ #include <linux/fs.h>
++ #include <linux/fd.h>
++#elif defined(__FreeBSD__) || defined(__APPLE__)
++ #include <sys/disk.h>
++
++ #define BLOCK_SIZE_BITS 10
++ #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
++
++ struct floppy_struct {
++ unsigned int size; /* nr of sectors total */
++ unsigned int sect; /* sectors per track */
++ unsigned int head; /* nr of heads */
++ unsigned int track; /* nr of tracks */
++ unsigned int stretch; /* bit 0 !=0 means double track steps */
++ /* bit 1 != 0 means swap sides */
++ /* bits 2..9 give the first sector */
++ /* number (the LSB is flipped) */
++ unsigned char gap; /* gap1 size */
++ unsigned char rate; /* data rate. |= 0x40 for perpendicular */
++ unsigned char spec1; /* stepping rate, head unload time */
++ unsigned char fmt_gap; /* gap2 size */
++ const char * name; /* used only for predefined formats */
++ };
++
++ struct hd_geometry {
++ unsigned char heads;
++ unsigned char sectors;
++ unsigned short cylinders;
++ unsigned long start;
++ };
++#endif
++
+ #include "msdos_fs.h"
+
+ /* In earlier versions, an own llseek() was used, but glibc lseek() is
+@@ -511,7 +541,9 @@ static void check_mount(char *device_name)
+ static void establish_params(int device_num, int size)
+ {
+ long loop_size;
++#if defined(__linux__) || defined(__FreeBSD__)
+ struct hd_geometry geometry;
++#endif
+ struct floppy_struct param;
+ int def_root_dir_entries = 512;
+
+@@ -549,9 +581,12 @@ static void establish_params(int device_num, int size)
+ }
+
+ } else { /* is a floppy diskette */
+-
++#if defined(__linux__)
+ if (ioctl(dev, FDGETPRM, &param)) /* Can we get the diskette geometry? */
+ die("unable to get diskette geometry for '%s'");
++#else
++ die("unable to get diskette geometry for '%s'");
++#endif
+ }
+ bs.secs_track = htole16(param.sect); /* Set up the geometry information */
+ bs.heads = htole16(param.head);
+@@ -594,8 +629,18 @@ floppy_default:
+ goto floppy_default;
+ }
+ } else if ((device_num & 0xff00) == 0x0700) { /* This is a loop device */
++#if defined(__FreeBSD__)
++ if (ioctl(dev, DIOCGSECTORSIZE, &loop_size))
++ die("unable to get loop device size");
++#elif defined(__linux__)
+ if (ioctl(dev, BLKGETSIZE, &loop_size))
+ die("unable to get loop device size");
++#elif defined(__APPLE__)
++ if (ioctl(dev, DKIOCGETBLOCKSIZE, &loop_size))
++ die("unable to get loop device size");
++#else
++ die("unable to get loop device size");
++#endif
+
+ switch (loop_size) { /* Assuming the loop device -> floppy later */
+ case 720: /* 5.25", 2, 9, 40 - 360K */
+@@ -651,6 +696,17 @@ floppy_default:
+ {
+ /* Can we get the drive geometry? (Note I'm not too sure about */
+ /* whether to use HDIO_GETGEO or HDIO_REQ) */
++#if defined(__FreeBSD__)
++ if (ioctl(dev, DIOCGFWSECTORS, &geometry.sectors) || ioctl(dev, DIOCGFWHEADS, &geometry.heads) || geometry.sectors == 0
++ || geometry.heads == 0) {
++ printf("unable to get drive geometry, using default 255/63\n");
++ bs.secs_track = htole16(63);
++ bs.heads = htole16(255);
++ } else {
++ bs.secs_track = htole16(geometry.sectors); /* Set up the geometry information */
++ bs.heads = htole16(geometry.heads);
++ }
++#elif defined(__linux__)
+ if (ioctl(dev, HDIO_GETGEO, &geometry) || geometry.sectors == 0
+ || geometry.heads == 0) {
+ printf("unable to get drive geometry, using default 255/63\n");
+@@ -662,6 +718,11 @@ floppy_default:
+ if (!hidden_sectors_by_user)
+ hidden_sectors = htole32(geometry.start);
+ }
++#else
++ printf("unable to get drive geometry, using default 255/63\n");
++ bs.secs_track = htole16(63);
++ bs.heads = htole16(255);
++#endif
+ def_hd_params:
+ bs.media = (char)0xf8; /* Set up the media descriptor for a hard drive */
+ if (!size_fat && blocks * SECTORS_PER_BLOCK > 1064960) {
+@@ -1693,6 +1754,15 @@ int main(int argc, char **argv)
+ die("Device partition expected, not making filesystem on entire device '%s' (use -I to override)");
+
+ if (sector_size_set) {
++#if defined(__FreeBSD__)
++ if (ioctl(dev, DIOCGSECTORSIZE, &min_sector_size) >= 0)
++ if (sector_size < min_sector_size) {
++ sector_size = min_sector_size;
++ fprintf(stderr,
++ "Warning: sector size was set to %d (minimal for this device)\n",
++ sector_size);
++ }
++#elif defined(__linux__)
+ if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0)
+ if (sector_size < min_sector_size) {
+ sector_size = min_sector_size;
+@@ -1700,11 +1770,32 @@ int main(int argc, char **argv)
+ "Warning: sector size was set to %d (minimal for this device)\n",
+ sector_size);
+ }
++#elif defined(__APPLE__)
++ if (ioctl(dev, DKIOCGETPHYSICALBLOCKSIZE, &min_sector_size) >= 0)
++ if (sector_size < min_sector_size) {
++ sector_size = min_sector_size;
++ fprintf(stderr,
++ "Warning: sector size was set to %d (minimal for this device)\n",
++ sector_size);
++ }
++#endif
+ } else {
++#if defined(__FreeBSD__)
++ if (ioctl(dev, DIOCGSECTORSIZE, &min_sector_size) >= 0) {
++ sector_size = min_sector_size;
++ sector_size_set = 1;
++ }
++#elif defined(__linux__)
+ if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0) {
+ sector_size = min_sector_size;
+ sector_size_set = 1;
+ }
++#elif defined(__APPLE__)
++ if (ioctl(dev, DKIOCGETPHYSICALBLOCKSIZE, &min_sector_size) >= 0) {
++ sector_size = min_sector_size;
++ sector_size_set = 1;
++ }
++#endif
+ }
+
+ if (sector_size > 4096)
+--
+1.9.1
+
diff --git a/tools/dosfstools/patches/0014-Add-OSX-and-FreeBSD-support.patch b/tools/dosfstools/patches/0014-Add-OSX-and-FreeBSD-support.patch
new file mode 100644
index 0000000..cc3c2c3
--- /dev/null
+++ b/tools/dosfstools/patches/0014-Add-OSX-and-FreeBSD-support.patch
@@ -0,0 +1,334 @@
+From 514985ae786dcde9842e46899ef5b6218662a119 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
+Date: Sat, 7 Mar 2015 16:32:51 +0100
+Subject: [PATCH 14/14] Add OSX and FreeBSD support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ Makefile | 9 ++++++++-
+ src/boot.c | 1 +
+ src/check.c | 1 +
+ src/endian.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/fat.c | 1 +
+ src/fatlabel.c | 1 +
+ src/fsck.fat.h | 3 +--
+ src/io.h | 2 +-
+ src/lfn.c | 1 +
+ src/mkfs.fat.c | 19 ++++++++++++++++---
+ src/types.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 11 files changed, 145 insertions(+), 7 deletions(-)
+ create mode 100644 src/endian.h
+ create mode 100644 src/types.h
+
+diff --git a/Makefile b/Makefile
+index 1593f3d..7359a79 100644
+--- a/Makefile
++++ b/Makefile
+@@ -28,12 +28,19 @@ DOCDIR = $(PREFIX)/share/doc
+ MANDIR = $(PREFIX)/share/man
+
+ #OPTFLAGS = -O2 -fomit-frame-pointer -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
+-OPTFLAGS = -O2 -fomit-frame-pointer -D_GNU_SOURCE $(shell getconf LFS_CFLAGS)
++OPTFLAGS = -O2 -fomit-frame-pointer -D_GNU_SOURCE
+ #WARNFLAGS = -Wall -pedantic -std=c99
+ WARNFLAGS = -Wall -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings
+ DEBUGFLAGS = -g
+ CFLAGS += $(OPTFLAGS) $(WARNFLAGS) $(DEBUGFLAGS)
+
++UNAME_S := $(shell uname -s)
++ifeq ($(UNAME_S),Darwin)
++ LDLIBS += -liconv
++else
++ OPTFLAGS += $(shell getconf LFS_CFLAGS)
++endif
++
+ VPATH = src
+
+ all: build
+diff --git a/src/boot.c b/src/boot.c
+index 0c0918f..1da9889 100644
+--- a/src/boot.c
++++ b/src/boot.c
+@@ -31,6 +31,7 @@
+ #include <time.h>
+
+ #include "common.h"
++#include "endian.h"
+ #include "fsck.fat.h"
+ #include "fat.h"
+ #include "io.h"
+diff --git a/src/check.c b/src/check.c
+index 488f715..17ff16a 100644
+--- a/src/check.c
++++ b/src/check.c
+@@ -31,6 +31,7 @@
+ #include <time.h>
+
+ #include "common.h"
++#include "endian.h"
+ #include "fsck.fat.h"
+ #include "io.h"
+ #include "fat.h"
+diff --git a/src/endian.h b/src/endian.h
+new file mode 100644
+index 0000000..6613e65
+--- /dev/null
++++ b/src/endian.h
+@@ -0,0 +1,57 @@
++/* endian.h - Endian functions
++
++ Copyright (C) 2015 Álvaro Fernández Rojas <noltari@gmail.com>
++
++ 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.
++
++ 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, see <http://www.gnu.org/licenses/>.
++
++ The complete text of the GNU General Public License
++ can be found in /usr/share/common-licenses/GPL-3 file.
++*/
++
++#ifndef _ENDIAN_H
++#define _ENDIAN_H
++
++#if defined(__linux__)
++ #include <endian.h>
++#elif defined(__APPLE__)
++ #include <libkern/OSByteOrder.h>
++
++ #define htobe16(x) OSSwapHostToBigInt16(x)
++ #define htole16(x) OSSwapHostToLittleInt16(x)
++ #define be16toh(x) OSSwapBigToHostInt16(x)
++ #define le16toh(x) OSSwapLittleToHostInt16(x)
++
++ #define htobe32(x) OSSwapHostToBigInt32(x)
++ #define htole32(x) OSSwapHostToLittleInt32(x)
++ #define be32toh(x) OSSwapBigToHostInt32(x)
++ #define le32toh(x) OSSwapLittleToHostInt32(x)
++
++ #define htobe64(x) OSSwapHostToBigInt64(x)
++ #define htole64(x) OSSwapHostToLittleInt64(x)
++ #define be64toh(x) OSSwapBigToHostInt64(x)
++ #define le64toh(x) OSSwapLittleToHostInt64(x)
++#elif defined(__FreeBSD__)
++ #include <sys/endian.h>
++
++ #define be16toh(x) betoh16(x)
++ #define le16toh(x) letoh16(x)
++
++ #define be32toh(x) betoh32(x)
++ #define le32toh(x) letoh32(x)
++
++ #define be64toh(x) betoh64(x)
++ #define le64toh(x) letoh64(x)
++#endif
++
++#endif /* _ENDIAN_H */
+diff --git a/src/fat.c b/src/fat.c
+index 5a92f56..481c08a 100644
+--- a/src/fat.c
++++ b/src/fat.c
+@@ -30,6 +30,7 @@
+ #include <unistd.h>
+
+ #include "common.h"
++#include "endian.h"
+ #include "fsck.fat.h"
+ #include "io.h"
+ #include "check.h"
+diff --git a/src/fatlabel.c b/src/fatlabel.c
+index 1484ba5..6de831c 100644
+--- a/src/fatlabel.c
++++ b/src/fatlabel.c
+@@ -33,6 +33,7 @@
+ #include <ctype.h>
+
+ #include "common.h"
++#include "types.h"
+ #include "fsck.fat.h"
+ #include "io.h"
+ #include "boot.h"
+diff --git a/src/fsck.fat.h b/src/fsck.fat.h
+index e5f6178..8b0ccb9 100644
+--- a/src/fsck.fat.h
++++ b/src/fsck.fat.h
+@@ -27,11 +27,10 @@
+ #ifndef _DOSFSCK_H
+ #define _DOSFSCK_H
+
+-#include <fcntl.h>
+ #include <stddef.h>
+ #include <stdint.h>
+-#include <endian.h>
+
++#include "types.h"
+ #include "msdos_fs.h"
+
+ #define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+diff --git a/src/io.h b/src/io.h
+index d23d07e..eecfdc5 100644
+--- a/src/io.h
++++ b/src/io.h
+@@ -27,7 +27,7 @@
+ #ifndef _IO_H
+ #define _IO_H
+
+-#include <fcntl.h> /* for loff_t */
++#include "types.h"
+
+ loff_t llseek(int fd, loff_t offset, int whence);
+
+diff --git a/src/lfn.c b/src/lfn.c
+index 2601172..f679168 100644
+--- a/src/lfn.c
++++ b/src/lfn.c
+@@ -28,6 +28,7 @@
+ #include <time.h>
+
+ #include "common.h"
++#include "endian.h"
+ #include "io.h"
+ #include "fsck.fat.h"
+ #include "lfn.h"
+diff --git a/src/mkfs.fat.c b/src/mkfs.fat.c
+index 02e0918..f2cee09 100644
+--- a/src/mkfs.fat.c
++++ b/src/mkfs.fat.c
+@@ -48,8 +48,6 @@
+
+ #include <fcntl.h>
+ #include <sys/mount.h>
+-#include <endian.h>
+-#include <mntent.h>
+ #include <signal.h>
+ #include <string.h>
+ #include <stdio.h>
+@@ -61,13 +59,14 @@
+ #include <errno.h>
+ #include <ctype.h>
+ #include <stdint.h>
+-#include <endian.h>
+
+ #if defined(__linux__)
++ #include <mntent.h>
+ #include <linux/hdreg.h>
+ #include <linux/fs.h>
+ #include <linux/fd.h>
+ #elif defined(__FreeBSD__) || defined(__APPLE__)
++ #include <sys/mount.h>
+ #include <sys/disk.h>
+
+ #define BLOCK_SIZE_BITS 10
+@@ -97,7 +96,9 @@
+ };
+ #endif
+
++#include "endian.h"
+ #include "msdos_fs.h"
++#include "types.h"
+
+ /* In earlier versions, an own llseek() was used, but glibc lseek() is
+ * sufficient (or even better :) for 64 bit offsets in the meantime */
+@@ -525,6 +526,7 @@ static uint64_t count_blocks(char *filename, int *remainder)
+
+ static void check_mount(char *device_name)
+ {
++#if defined(__linux__)
+ FILE *f;
+ struct mntent *mnt;
+
+@@ -534,6 +536,17 @@ static void check_mount(char *device_name)
+ if (strcmp(device_name, mnt->mnt_fsname) == 0)
+ die("%s contains a mounted filesystem.");
+ endmntent(f);
++#elif defined(__APPLE__) || defined(__FreeBSD__)
++ struct statfs* mounts;
++ int num_mounts = getmntinfo(&mounts, MNT_WAIT);
++ if (num_mounts < 0)
++ return;
++ for ( int i = 0; i < num_mounts; i++ )
++ {
++ if (strcmp(device_name, mounts[i].f_mntfromname) == 0)
++ die("%s contains a mounted filesystem.");
++ }
++#endif
+ }
+
+ /* Establish the geometry and media parameters for the device */
+diff --git a/src/types.h b/src/types.h
+new file mode 100644
+index 0000000..a3f1a47
+--- /dev/null
++++ b/src/types.h
+@@ -0,0 +1,57 @@
++/* types.h - Missing types
++
++ Copyright (C) 2015 Álvaro Fernández Rojas <noltari@gmail.com>
++
++ 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.
++
++ 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, see <http://www.gnu.org/licenses/>.
++
++ The complete text of the GNU General Public License
++ can be found in /usr/share/common-licenses/GPL-3 file.
++*/
++
++#ifndef _TYPES_H
++#define _TYPES_H
++
++#if defined(__linux__)
++ #include <fcntl.h>
++#elif defined(__APPLE__)
++ #ifndef loff_t
++ typedef long long loff_t;
++ #endif /* loff_t */
++
++ #ifndef lseek64
++ #define lseek64 lseek
++ #endif /* lseek64 */
++
++ #ifndef off64_t
++ #ifdef _LP64
++ typedef off_t off64_t;
++ #else
++ typedef __longlong_t off64_t;
++ #endif /* _LP64 */
++ #endif /* off64_t */
++#elif defined(__FreeBSD__)
++ #ifndef loff_t
++ typedef long long loff_t;
++ #endif /* loff_t */
++
++ #ifndef lseek64
++ #define lseek64 lseek
++ #endif /* lseek64 */
++
++ #ifndef off64_t
++ typedef off_t off64_t;
++ #endif /* off64_t */
++#endif
++
++#endif /* _TYPES_H */
+--
+1.9.1
+
diff --git a/tools/e2fsprogs/Makefile b/tools/e2fsprogs/Makefile
new file mode 100644
index 0000000..5632e19
--- /dev/null
+++ b/tools/e2fsprogs/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2010-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=e2fsprogs
+PKG_VERSION:=1.42.8
+PKG_MD5SUM:=8ef664b6eb698aa6b733df59b17b9ed4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/e2fsprogs
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CFLAGS += $(FPIC)
+
+HOST_CONFIGURE_ARGS += \
+ --disable-shared \
+ --disable-elf-shlibs \
+ --enable-static \
+ --enable-dynamic-e2fsck \
+ --disable-tls \
+ --disable-nls
+
+define Host/Prepare
+ $(call Host/Prepare/Default)
+ rm -rf $(HOST_BUILD_DIR)/doc
+endef
+
+define Host/Install
+ $(Host/Install/Default)
+ $(MAKE) -C $(HOST_BUILD_DIR)/lib/uuid install
+ mkdir -p $(STAGING_DIR_HOST)/include/e2fsprogs
+ $(CP) $(STAGING_DIR_HOST)/include/uuid $(STAGING_DIR_HOST)/include/e2fsprogs/
+ rm -rf $(STAGING_DIR_HOST)/include/uuid
+ $(INSTALL_DATA) $(HOST_BUILD_DIR)/lib/uuid/libuuid.a $(STAGING_DIR_HOST)/lib/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/e2fsck
+ rm -f $(STAGING_DIR_HOST)/bin/tune2fs
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/e2fsprogs/patches/001-exit_0_on_corrected_errors.patch b/tools/e2fsprogs/patches/001-exit_0_on_corrected_errors.patch
new file mode 100644
index 0000000..67a30f6
--- /dev/null
+++ b/tools/e2fsprogs/patches/001-exit_0_on_corrected_errors.patch
@@ -0,0 +1,11 @@
+--- a/e2fsck/e2fsck.h
++++ b/e2fsck/e2fsck.h
+@@ -73,7 +73,7 @@
+ * Exit codes used by fsck-type programs
+ */
+ #define FSCK_OK 0 /* No errors */
+-#define FSCK_NONDESTRUCT 1 /* File system errors corrected */
++#define FSCK_NONDESTRUCT 0 /* File system errors corrected */
+ #define FSCK_REBOOT 2 /* System should be rebooted */
+ #define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
+ #define FSCK_ERROR 8 /* Operational error */
diff --git a/tools/e2fsprogs/patches/002-dont-build-e4defrag.patch b/tools/e2fsprogs/patches/002-dont-build-e4defrag.patch
new file mode 100644
index 0000000..9f6e7b1
--- /dev/null
+++ b/tools/e2fsprogs/patches/002-dont-build-e4defrag.patch
@@ -0,0 +1,11 @@
+--- a/misc/Makefile.in
++++ b/misc/Makefile.in
+@@ -11,7 +11,7 @@ INSTALL = @INSTALL@
+
+ @MCONFIG@
+
+-@DEFRAG_CMT@@LINUX_CMT@E4DEFRAG_PROG= e4defrag
++@DEFRAG_CMT@@LINUX_CMT@E4DEFRAG_PROG=
+ @DEFRAG_CMT@@LINUX_CMT@E4DEFRAG_MAN= e4defrag.8
+
+ @IMAGER_CMT@E2IMAGE_PROG= e2image
diff --git a/tools/e2fsprogs/patches/003-openbsd-compat.patch b/tools/e2fsprogs/patches/003-openbsd-compat.patch
new file mode 100644
index 0000000..1f7cdca
--- /dev/null
+++ b/tools/e2fsprogs/patches/003-openbsd-compat.patch
@@ -0,0 +1,24 @@
+diff -Nur e2fsprogs-1.42.7.orig/lib/blkid/getsize.c e2fsprogs-1.42.7/lib/blkid/getsize.c
+--- e2fsprogs-1.42.7.orig/lib/blkid/getsize.c Fri Nov 30 03:40:18 2012
++++ e2fsprogs-1.42.7/lib/blkid/getsize.c Thu Mar 7 14:21:59 2013
+@@ -26,6 +26,9 @@
+ #include <fcntl.h>
+ #ifdef HAVE_SYS_IOCTL_H
+ #include <sys/ioctl.h>
++#ifdef __OpenBSD__
++#include <sys/dkio.h>
++#endif
+ #endif
+ #ifdef HAVE_LINUX_FD_H
+ #include <linux/fd.h>
+diff -Nur e2fsprogs-1.42.7.orig/lib/quota/mkquota.c e2fsprogs-1.42.7/lib/quota/mkquota.c
+--- e2fsprogs-1.42.7.orig/lib/quota/mkquota.c Wed Jan 2 01:47:20 2013
++++ e2fsprogs-1.42.7/lib/quota/mkquota.c Thu Mar 7 14:21:59 2013
+@@ -8,6 +8,7 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #include <errno.h>
++#include <stdint.h>
+ #include <string.h>
+ #include <fcntl.h>
+
diff --git a/tools/e2fsprogs/patches/004-freebsd-compat.patch b/tools/e2fsprogs/patches/004-freebsd-compat.patch
new file mode 100644
index 0000000..5eff499
--- /dev/null
+++ b/tools/e2fsprogs/patches/004-freebsd-compat.patch
@@ -0,0 +1,13 @@
+diff -Nur e2fsprogs-1.42.7.orig/lib/ext2fs/tdb.c e2fsprogs-1.42.7/lib/ext2fs/tdb.c
+--- e2fsprogs-1.42.7.orig/lib/ext2fs/tdb.c 2012-07-06 15:37:27.000000000 +0200
++++ e2fsprogs-1.42.7/lib/ext2fs/tdb.c 2013-03-07 14:54:59.000000000 +0100
+@@ -56,7 +56,9 @@
+ #include <utime.h>
+ #endif
+ #include <sys/stat.h>
++#ifndef __FreeBSD__
+ #include <sys/file.h>
++#endif
+ #include <fcntl.h>
+
+ #ifdef HAVE_SYS_MMAN_H
diff --git a/tools/e2fsprogs/patches/005-darwin-compat.patch b/tools/e2fsprogs/patches/005-darwin-compat.patch
new file mode 100644
index 0000000..bc81d86
--- /dev/null
+++ b/tools/e2fsprogs/patches/005-darwin-compat.patch
@@ -0,0 +1,22 @@
+--- a/lib/blkid/blkid_types.h.in
++++ b/lib/blkid/blkid_types.h.in
+@@ -9,6 +9,8 @@
+
+ @ASM_TYPES_HEADER@
+
++#include <stdint.h>
++
+ #ifdef __U8_TYPEDEF
+ typedef __U8_TYPEDEF __u8;
+ #else
+--- a/lib/ext2fs/ext2_types.h.in
++++ b/lib/ext2fs/ext2_types.h.in
+@@ -9,6 +9,8 @@
+
+ @ASM_TYPES_HEADER@
+
++#include <stdint.h>
++
+ #ifdef __U8_TYPEDEF
+ typedef __U8_TYPEDEF __u8;
+ #else
diff --git a/tools/elftosb/Makefile b/tools/elftosb/Makefile
new file mode 100644
index 0000000..5adafef
--- /dev/null
+++ b/tools/elftosb/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=elftosb
+PKG_VERSION:=10.12.01
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://repository.timesys.com/buildsources/e/elftosb/elftosb-10.12.01/
+PKG_MD5SUM:=e8005d606c1e0bb3507c82f6eceb3056
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) LDFLAGS="$(HOST_LDFLAGS)"
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/bld/linux/elftosb $(STAGING_DIR_HOST)/bin/elftosb
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/elftosb/patches/001-libm.patch b/tools/elftosb/patches/001-libm.patch
new file mode 100644
index 0000000..02705d2
--- /dev/null
+++ b/tools/elftosb/patches/001-libm.patch
@@ -0,0 +1,11 @@
+--- elftosb-10.12.01/makefile.rules 2012-03-15 11:01:44.979020178 -0400
++++ elftosb-10.12.01/makefile.rules 2012-03-15 11:01:16.332761989 -0400
+@@ -101,7 +101,7 @@
+ keygen.o
+
+
+-LIBS = -lstdc++
++LIBS = -lstdc++ -lm
+
+
+ ifeq ("${UNAMES}", "Linux")
diff --git a/tools/elftosb/patches/002-fix-header-path.patch b/tools/elftosb/patches/002-fix-header-path.patch
new file mode 100644
index 0000000..5e3b509
--- /dev/null
+++ b/tools/elftosb/patches/002-fix-header-path.patch
@@ -0,0 +1,19 @@
+This package had an absolute path for sys/types.h, which doesn't
+make much sense. It breaks on newer Ubuntu systems, and probably many
+others once multiarch becomes more common.
+
+This patch makes the types a relative path, and allows the system
+to use whatever include paths it feels are correct.
+
+diff -Naurp elftosb-10.12.01-orig/common/stdafx.h elftosb-10.12.01/common/stdafx.h
+--- elftosb-10.12.01-orig/common/stdafx.h 2012-07-12 13:30:10.990249396 -0400
++++ elftosb-10.12.01/common/stdafx.h 2012-07-12 13:30:06.858249391 -0400
+@@ -27,7 +27,7 @@
+ // For Linux systems only, types.h only defines the signed
+ // integer types. This is not professional code.
+ // Update: They are defined in the header files in the more recent version of redhat enterprise gcc.
+-#include "/usr/include/sys/types.h"
++#include <sys/types.h>
+ #include <stdint.h>
+ //typedef unsigned long uint32_t;
+ //typedef unsigned short uint16_t;
diff --git a/tools/elftosb/patches/003-use-ldflags.patch b/tools/elftosb/patches/003-use-ldflags.patch
new file mode 100644
index 0000000..82fd1e8
--- /dev/null
+++ b/tools/elftosb/patches/003-use-ldflags.patch
@@ -0,0 +1,26 @@
+--- a/makefile.rules
++++ b/makefile.rules
+@@ -131,19 +131,20 @@ exec_always:
+ @echo "LIBS = ${LIBS}"
+ @echo "EXEC_FILE = ${EXEC_FILE}"
+ @echo "BUILD_DIR = ${BUILD_DIR}"
++ @echo "LDFLAGS = ${LDFLAGS}"
+
+ clean:
+ rm -f ${OBJ_FILES_ELFTOSB2} ${OBJ_FILES_SBTOOL} ${OBJ_FILES_KEYGEN} \
+ ${EXEC_FILE_ELFTOSB2} ${EXEC_FILE_SBTOOL} ${EXEC_FILE_KEYGEN}
+
+ elftosb: ${OBJ_FILES_ELFTOSB2}
+- gcc ${OBJ_FILES_ELFTOSB2} ${LIBS} -o ${EXEC_FILE_ELFTOSB2}
++ gcc ${OBJ_FILES_ELFTOSB2} ${LIBS} ${LDFLAGS} -o ${EXEC_FILE_ELFTOSB2}
+
+ sbtool: ${OBJ_FILES_SBTOOL}
+- gcc ${OBJ_FILES_SBTOOL} ${LIBS} -o ${EXEC_FILE_SBTOOL}
++ gcc ${OBJ_FILES_SBTOOL} ${LIBS} ${LDFLAGS} -o ${EXEC_FILE_SBTOOL}
+
+ keygen: ${OBJ_FILES_KEYGEN}
+- gcc ${OBJ_FILES_KEYGEN} ${LIBS} -o ${EXEC_FILE_KEYGEN}
++ gcc ${OBJ_FILES_KEYGEN} ${LIBS} ${LDFLAGS} -o ${EXEC_FILE_KEYGEN}
+
+
+ #ifeq ("${UNAMES}", "Linux")
diff --git a/tools/expat/Makefile b/tools/expat/Makefile
new file mode 100644
index 0000000..dfd5f28
--- /dev/null
+++ b/tools/expat/Makefile
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=expat
+PKG_VERSION:=2.1.0
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_MD5SUM:=dd7dab7a5fea97d2a6a43f511449b7cd
+PKG_SOURCE_URL:=@SF/expat
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Install
+ $(MAKE) -C $(HOST_BUILD_DIR) install
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/findutils/Makefile b/tools/findutils/Makefile
new file mode 100644
index 0000000..970cff8
--- /dev/null
+++ b/tools/findutils/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2006-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=findutils
+PKG_VERSION:=4.4.2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=351cc4adb07d54877fa15f75fb77d39f
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+$(eval $(call HostBuild))
diff --git a/tools/findutils/patches/21-Fix-time_t-vs-long-int-mismatches.patch b/tools/findutils/patches/21-Fix-time_t-vs-long-int-mismatches.patch
new file mode 100644
index 0000000..f3ebb05
--- /dev/null
+++ b/tools/findutils/patches/21-Fix-time_t-vs-long-int-mismatches.patch
@@ -0,0 +1,158 @@
+>From 0078a6c784da339cc529b4f0bf1156ca52692e4c Mon Sep 17 00:00:00 2001
+From: Adam Borowski <kilobyte@angband.pl>
+Date: Thu, 6 Jun 2013 18:41:53 +0000
+Subject: [PATCH] Fix time_t vs long int mismatches.
+
+Old gnulibs used randomly either time_t or long int, with a compile-time
+assert to ensure sizeof(time_t) <= sizeof(long int). This is not the
+case on x32 where the machine word is 32 bit, yet time_t is 64 bit to
+be able to handle dates after 2038.
+
+This is not relevant for modern versions of gnulib which has rewritten
+this code, but, sadly, findutils 4.4.* uses an embedded copy of ancient
+gnulib.
+---
+ gnulib/lib/getdate.y | 46 ++++++++++++++++++++++++----------------------
+ 1 file changed, 24 insertions(+), 22 deletions(-)
+
+diff --git a/gnulib/lib/getdate.y b/gnulib/lib/getdate.y
+index e292f5e..347cc77 100644
+--- a/gnulib/lib/getdate.y
++++ b/gnulib/lib/getdate.y
+@@ -112,16 +112,18 @@
+ /* Lots of this code assumes time_t and time_t-like values fit into
+ long int. It also assumes that signed integer overflow silently
+ wraps around, but there's no portable way to check for that at
+- compile-time. */
++ compile-time.
++ [1KB]: replaced suspicious uses of long_t by time_t.
+ verify (TYPE_IS_INTEGER (time_t));
+ verify (LONG_MIN <= TYPE_MINIMUM (time_t) && TYPE_MAXIMUM (time_t) <= LONG_MAX);
++*/
+
+ /* An integer value, and the number of digits in its textual
+ representation. */
+ typedef struct
+ {
+ bool negative;
+- long int value;
++ time_t value;
+ size_t digits;
+ } textint;
+
+@@ -206,7 +208,7 @@ typedef struct
+ union YYSTYPE;
+ static int yylex (union YYSTYPE *, parser_control *);
+ static int yyerror (parser_control const *, char const *);
+-static long int time_zone_hhmm (textint, long int);
++static time_t time_zone_hhmm (textint, time_t);
+
+ /* Extract into *PC any date and time info from a string of digits
+ of the form e.g., YYYYMMDD, YYMMDD, HHMM, HH (and sometimes YYY,
+@@ -817,8 +819,8 @@ static table const military_table[] =
+ minutes. If MM is negative, then S is of the form HHMM and needs
+ to be picked apart; otherwise, S is of the form HH. */
+
+-static long int
+-time_zone_hhmm (textint s, long int mm)
++static time_t
++time_zone_hhmm (textint s, time_t mm)
+ {
+ if (mm < 0)
+ return (s.value / 100) * 60 + s.value % 100;
+@@ -884,7 +886,7 @@ lookup_zone (parser_control const *pc, char const *name)
+ measured in seconds, ignoring leap seconds.
+ The body of this function is taken directly from the GNU C Library;
+ see src/strftime.c. */
+-static long int
++static time_t
+ tm_diff (struct tm const *a, struct tm const *b)
+ {
+ /* Compute intervening leap days correctly even if year is negative.
+@@ -896,9 +898,9 @@ tm_diff (struct tm const *a, struct tm const *b)
+ int a400 = SHR (a100, 2);
+ int b400 = SHR (b100, 2);
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+- long int ayear = a->tm_year;
+- long int years = ayear - b->tm_year;
+- long int days = (365 * years + intervening_leap_days
++ time_t ayear = a->tm_year;
++ time_t years = ayear - b->tm_year;
++ time_t int days = (365 * years + intervening_leap_days
+ + (a->tm_yday - b->tm_yday));
+ return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+@@ -1200,7 +1202,7 @@ bool
+ get_date (struct timespec *result, char const *p, struct timespec const *now)
+ {
+ time_t Start;
+- long int Start_ns;
++ time_t Start_ns;
+ struct tm const *tmp;
+ struct tm tm;
+ struct tm tm0;
+@@ -1407,16 +1409,16 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
+ problem, set the time zone to 1 hour behind UTC temporarily
+ by setting TZ="XXX1:00" and try mktime again. */
+
+- long int time_zone = pc.time_zone;
+- long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
+- long int abs_time_zone_hour = abs_time_zone / 60;
++ time_t time_zone = pc.time_zone;
++ time_t abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
++ time_t abs_time_zone_hour = abs_time_zone / 60;
+ int abs_time_zone_min = abs_time_zone % 60;
+ char tz1buf[sizeof "XXX+0:00"
+ + sizeof pc.time_zone * CHAR_BIT / 3];
+ if (!tz_was_altered)
+ tz0 = get_tz (tz0buf);
+ sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),
+- abs_time_zone_hour, abs_time_zone_min);
++ (long int)abs_time_zone_hour, abs_time_zone_min);
+ if (setenv ("TZ", tz1buf, 1) != 0)
+ goto fail;
+ tz_was_altered = true;
+@@ -1439,7 +1441,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
+
+ if (pc.zones_seen)
+ {
+- long int delta = pc.time_zone * 60;
++ time_t delta = pc.time_zone * 60;
+ time_t t1;
+ #ifdef HAVE_TM_GMTOFF
+ delta -= tm.tm_gmtoff;
+@@ -1486,16 +1488,16 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
+ must be applied before relative times, and if mktime is applied
+ again the time zone will be lost. */
+ {
+- long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns;
+- long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
++ time_t sum_ns = pc.seconds.tv_nsec + pc.rel.ns;
++ time_t normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
+ time_t t0 = Start;
+- long int d1 = 60 * 60 * pc.rel.hour;
++ time_t d1 = 60 * 60 * pc.rel.hour;
+ time_t t1 = t0 + d1;
+- long int d2 = 60 * pc.rel.minutes;
++ time_t d2 = 60 * pc.rel.minutes;
+ time_t t2 = t1 + d2;
+- long int d3 = pc.rel.seconds;
++ time_t d3 = pc.rel.seconds;
+ time_t t3 = t2 + d3;
+- long int d4 = (sum_ns - normalized_ns) / BILLION;
++ time_t d4 = (sum_ns - normalized_ns) / BILLION;
+ time_t t4 = t3 + d4;
+
+ if ((d1 / (60 * 60) ^ pc.rel.hour)
+@@ -1542,7 +1544,7 @@ main (int ac, char **av)
+ printf ("Bad format - couldn't convert.\n");
+ else if (! (tm = localtime (&d.tv_sec)))
+ {
+- long int sec = d.tv_sec;
++ time_t sec = d.tv_sec;
+ printf ("localtime (%ld) failed\n", sec);
+ }
+ else
+--
+1.8.3.rc3
+
diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile
new file mode 100644
index 0000000..bd69cb4
--- /dev/null
+++ b/tools/firmware-utils/Makefile
@@ -0,0 +1,82 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME := firmware-utils
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define cc
+ $(HOSTCC) $(HOST_CFLAGS) -include endian.h $(HOST_LDFLAGS) -o $(HOST_BUILD_DIR)/bin/$(firstword $(1)) $(foreach src,$(1),src/$(src).c) $(2)
+endef
+
+define Host/Compile
+ mkdir -p $(HOST_BUILD_DIR)/bin
+ $(call cc,addpattern)
+ $(call cc,asustrx)
+ $(call cc,trx)
+ $(call cc,motorola-bin)
+ $(call cc,dgfirmware)
+ $(call cc,mksenaofw md5)
+ $(call cc,trx2usr)
+ $(call cc,ptgen)
+ $(call cc,airlink)
+ $(call cc,srec2bin)
+ $(call cc,mkmylofw)
+ $(call cc,mkcsysimg)
+ $(call cc,mkzynfw)
+ $(call cc,lzma2eva,-lz)
+ $(call cc,mkcasfw)
+ $(call cc,mkfwimage,-lz)
+ $(call cc,mkfwimage2,-lz)
+ $(call cc,imagetag imagetag_cmdline cyg_crc32)
+ $(call cc,add_header)
+ $(call cc,makeamitbin)
+ $(call cc,encode_crc)
+ $(call cc,nand_ecc)
+ $(call cc,mkplanexfw sha1)
+ $(call cc,mktplinkfw md5)
+ $(call cc,mktplinkfw2 md5)
+ $(call cc,tplink-safeloader md5, -Wall)
+ $(call cc,pc1crypt)
+ $(call cc,osbridge-crc)
+ $(call cc,wrt400n cyg_crc32)
+ $(call cc,mkdniimg)
+ $(call cc,mktitanimg)
+ $(call cc,mkchkimg)
+ $(call cc,mkzcfw cyg_crc32)
+ $(call cc,spw303v)
+ $(call cc,zyxbcm)
+ $(call cc,trx2edips)
+ $(call cc,xorimage)
+ $(call cc,buffalo-enc buffalo-lib, -Wall)
+ $(call cc,buffalo-tag buffalo-lib, -Wall)
+ $(call cc,buffalo-tftp buffalo-lib, -Wall)
+ $(call cc,mkwrgimg md5, -Wall)
+ $(call cc,mkedimaximg)
+ $(call cc,mkbrncmdline)
+ $(call cc,mkbrnimg)
+ $(call cc,mkdapimg)
+ $(call cc, mkcameofw, -Wall)
+ $(call cc,seama md5)
+ $(call cc,fix-u-media-header cyg_crc32,-Wall)
+ $(call cc,hcsmakeimage bcmalgo)
+ $(call cc,mkporayfw, -Wall)
+ $(call cc,mkhilinkfw, -lcrypto)
+ $(call cc,mkdcs932, -Wall)
+ $(call cc,mkheader_gemtek,-lz)
+ $(call cc,mkrtn56uimg, -lz)
+ $(call cc,dgn3500sum)
+ $(call cc,edimax_fw_header, -Wall)
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/bin/* $(STAGING_DIR_HOST)/bin/
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/firmware-utils/src/add_header.c b/tools/firmware-utils/src/add_header.c
new file mode 100644
index 0000000..37775c3
--- /dev/null
+++ b/tools/firmware-utils/src/add_header.c
@@ -0,0 +1,138 @@
+/*
+ * add_header.c - partially based on OpenWrt's motorola-bin.c
+ *
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ * Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * The add_header utility used by various vendors preprends the buf
+ * image with a header containing a CRC32 value which is generated for the
+ * model id + reserved space for CRC32 + buf, then replaces the reserved
+ * area with the actual CRC32. This replacement tool mimics this behavior.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#define BPB 8 /* bits/byte */
+
+static uint32_t crc32[1<<BPB];
+
+static void init_crc32()
+{
+ const uint32_t poly = ntohl(0x2083b8ed);
+ int n;
+
+ for (n = 0; n < 1<<BPB; n++) {
+ uint32_t crc = n;
+ int bit;
+
+ for (bit = 0; bit < BPB; bit++)
+ crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
+ crc32[n] = crc;
+ }
+}
+
+static uint32_t crc32buf(unsigned char *buf, size_t len)
+{
+ uint32_t crc = 0xFFFFFFFF;
+
+ for (; len; len--, buf++)
+ crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB);
+ return ~crc;
+}
+
+struct header {
+ unsigned char model[16];
+ uint32_t crc;
+};
+
+static void usage(const char *) __attribute__ (( __noreturn__ ));
+
+static void usage(const char *mess)
+{
+ fprintf(stderr, "Error: %s\n", mess);
+ fprintf(stderr, "Usage: add_header model_id input_file output_file\n");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ off_t len; // of original buf
+ off_t buflen; // of the output file
+ int fd;
+ void *input_file; // pointer to the input file (mmmapped)
+ struct header header;
+ unsigned char *buf; // pointer to prefix + copy of original buf
+
+ // verify parameters
+
+ if (argc != 4)
+ usage("wrong number of arguments");
+
+ // mmap input_file
+ if ((fd = open(argv[2], O_RDONLY)) < 0
+ || (len = lseek(fd, 0, SEEK_END)) < 0
+ || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1)
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error loading file %s: %s\n", argv[2], strerror(errno));
+ exit(1);
+ }
+
+ buflen = len + sizeof(header);
+
+ init_crc32();
+
+ // copy model name into header
+ strncpy(header.model, argv[1], sizeof(header.model));
+ header.crc = 0;
+
+ // create a firmware image in memory and copy the input_file to it
+ buf = malloc(buflen);
+ memcpy(buf, &header, sizeof(header));
+ memcpy(&buf[sizeof(header)], input_file, len);
+
+ // CRC of temporary header + buf
+ header.crc = htonl(crc32buf(buf, buflen));
+
+ memcpy(buf, &header, sizeof(header));
+
+ // write the buf
+ if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0
+ || write(fd, buf, buflen) != buflen
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno));
+ exit(2);
+ }
+
+ free(buf);
+
+ munmap(input_file,len);
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/addpattern.c b/tools/firmware-utils/src/addpattern.c
new file mode 100644
index 0000000..1d72285
--- /dev/null
+++ b/tools/firmware-utils/src/addpattern.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* July 29, 2004
+ *
+ * This is a hacked replacement for the 'addpattern' utility used to
+ * create wrt54g .bin firmware files. It isn't pretty, but it does
+ * the job for me.
+ *
+ * Extensions:
+ * -v allows setting the version string on the command line.
+ * -{0|1} sets the (currently ignored) hw_ver flag in the header
+ * to 0 or 1 respectively.
+ */
+
+/* January 12, 2005
+ *
+ * Modified by rodent at rodent dot za dot net
+ * Support added for the new WRT54G v2.2 and WRT54GS v1.1 "flags"
+ * Without the flags set to 0x7, the above units will refuse to flash.
+ *
+ * Extensions:
+ * -{0|1|2} sets {0|1} sets hw_ver flag to 0/1. {2} sets hw_ver to 1
+ * and adds the new hardware "flags" for the v2.2/v1.1 units
+*/
+
+/* January 1, 2007
+ *
+ * Modified by juan.i.gonzalez at subdown dot net
+ * Support added for the AG241v2 and similar
+ *
+ * Extensions:
+ * -r #.# adds revision hardware flags. AG241v2 and similar.
+ *
+ * AG241V2 firmware sets the hw_ver to 0x44.
+ *
+ * Example: -r 2.0
+ *
+ * Convert 2.0 to 20 to be an integer, and add 0x30 to skip special ASCII
+ * #define HW_Version ((HW_REV * 10) + 0x30) -> from cyutils.h
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/**********************************************************************/
+
+#define CODE_ID "U2ND" /* from code_pattern.h */
+#define CODE_PATTERN "W54S" /* from code_pattern.h */
+#define PBOT_PATTERN "PBOT"
+
+#define CYBERTAN_VERSION "v3.37.2" /* from cyutils.h */
+
+/* WRT54G v2.2 and WRT54GS v1.1 "flags" (from 3.37.32 firmware cyutils.h) */
+#define SUPPORT_4712_CHIP 0x0001
+#define SUPPORT_INTEL_FLASH 0x0002
+#define SUPPORT_5325E_SWITCH 0x0004
+/* (from 3.00.24 firmware cyutils.h) */
+#define SUPPORT_4704_CHIP 0x0008
+#define SUPPORT_5352E_CHIP 0x0010
+/* (from WD My Net Wi-Fi Range Extender's cyutils.s) */
+#define SUPPORT_4703_CHIP 0x0020
+
+struct code_header { /* from cyutils.h */
+ char magic[8];
+ char fwdate[3];
+ char fwvern[3];
+ char id[4]; /* U2ND */
+ char hw_ver; /* 0: for 4702, 1: for 4712 -- new in 2.04.3 */
+
+ unsigned char sn; // Serial Number
+ unsigned char flags[2]; /* SUPPORT_ flags new for 3.37.2 (WRT54G v2.2 and WRT54GS v1.1) */
+ unsigned char stable[2]; // The image is stable (for dual image)
+ unsigned char try1[2]; // Try to boot image first time (for dual image)
+ unsigned char try2[2]; // Try to boot image second time (for dual image)
+ unsigned char try3[2]; // Try to boot image third time (for dual_image)
+ unsigned char res3[2];
+} ;
+
+struct board_info {
+ char *id;
+ char *pattern;
+ char hw_ver;
+ char sn;
+ char flags[2];
+};
+
+struct board_info boards[] = {
+ {
+ .id = "WRT160NL",
+ .pattern = "NL16",
+ .hw_ver = 0x00,
+ .sn = 0x0f,
+ .flags = {0x3f, 0x00},
+ },
+ {
+ .id = "mynet-rext",
+ .pattern = "WDHNSTFH",
+ .hw_ver = 0x00,
+ .sn = 0x00,
+ .flags = {0x3f, 0x00},
+ }, {
+ /* Terminating entry */
+ .id = NULL,
+ }
+};
+
+/**********************************************************************/
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: addpattern [-i trxfile] [-o binfile] [-B board_id] [-p pattern] [-s serial] [-g] [-b] [-v v#.#.#] [-r #.#] [-{0|1|2|4|5}] -h\n");
+ exit(EXIT_FAILURE);
+}
+
+struct board_info *find_board(char *id)
+{
+ struct board_info *board;
+
+ for (board = boards; board->id != NULL; board++)
+ if (strcasecmp(id, board->id) == 0)
+ return board;
+
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ char buf[1024]; /* keep this at 1k or adjust garbage calc below */
+ struct code_header *hdr;
+ FILE *in = stdin;
+ FILE *out = stdout;
+ char *ifn = NULL;
+ char *ofn = NULL;
+ char *pattern = CODE_PATTERN;
+ char *pbotpat = PBOT_PATTERN;
+ char *version = CYBERTAN_VERSION;
+ char *board_id = NULL;
+ struct board_info *board = NULL;
+ int gflag = 0;
+ int pbotflag = 0;
+ int c;
+ int v0, v1, v2;
+ size_t off, n;
+ time_t t;
+ struct tm *ptm;
+
+ fprintf(stderr, "mjn3's addpattern replacement - v0.81\n");
+
+ hdr = (struct code_header *) buf;
+ memset(hdr, 0, sizeof(struct code_header));
+
+ while ((c = getopt(argc, argv, "i:o:p:s:gbv:01245hr:B:")) != -1) {
+ switch (c) {
+ case 'i':
+ ifn = optarg;
+ break;
+ case 'o':
+ ofn = optarg;
+ break;
+ case 'p':
+ pattern = optarg;
+ break;
+ case 's':
+ hdr->sn = (unsigned char) atoi (optarg);
+ break;
+ case 'g':
+ gflag = 1;
+ break;
+ case 'b':
+ pbotflag = 1;
+ break;
+ case 'v': /* extension to allow setting version */
+ version = optarg;
+ break;
+ case '0':
+ hdr->hw_ver = 0;
+ break;
+ case '1':
+ hdr->hw_ver = 1;
+ break;
+ case '2': /* new 54G v2.2 and 54GS v1.1 flags */
+ hdr->hw_ver = 1;
+ hdr->flags[0] |= SUPPORT_4712_CHIP;
+ hdr->flags[0] |= SUPPORT_INTEL_FLASH;
+ hdr->flags[0] |= SUPPORT_5325E_SWITCH;
+ break;
+ case '4':
+ /* V4 firmware sets the flags to 0x1f */
+ hdr->hw_ver = 0;
+ hdr->flags[0] = 0x1f;
+ break;
+ case '5':
+ /* V5 is appended to trxV2 image */
+ hdr->stable[0] = 0x73; // force image to be stable
+ hdr->stable[1] = 0x00;
+ hdr->try1[0] = 0x74; // force try1 to be set
+ hdr->try1[1] = 0x00;
+ hdr->try2[0] = hdr->try2[1] = 0xFF;
+ hdr->try3[0] = hdr->try3[1] = 0xFF;
+ break;
+ case 'r':
+ hdr->hw_ver = (char)(atof(optarg)*10)+0x30;
+ break;
+ case 'B':
+ board_id = optarg;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc || optind == 1) {
+ fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
+ usage();
+ }
+
+ if (board_id) {
+ board = find_board(board_id);
+ if (board == NULL) {
+ fprintf(stderr, "unknown board \"%s\"\n", board_id);
+ usage();
+ }
+ pattern = board->pattern;
+ hdr->hw_ver = board->hw_ver;
+ hdr->sn = board->sn;
+ hdr->flags[0] = board->flags[0];
+ hdr->flags[1] = board->flags[1];
+ }
+
+ if (strlen(pattern) > 8) {
+ fprintf(stderr, "illegal pattern \"%s\"\n", pattern);
+ usage();
+ }
+
+ if (ifn && !(in = fopen(ifn, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
+ usage();
+ }
+
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+ if (time(&t) == (time_t)(-1)) {
+ fprintf(stderr, "time call failed\n");
+ return EXIT_FAILURE;
+ }
+
+ ptm = localtime(&t);
+
+ if (3 != sscanf(version, "v%d.%d.%d", &v0, &v1, &v2)) {
+ fprintf(stderr, "bad version string \"%s\"\n", version);
+ return EXIT_FAILURE;
+ }
+
+ memcpy(hdr->magic, pattern, strlen(pattern));
+ if (pbotflag)
+ memcpy(&hdr->magic[4], pbotpat, 4);
+ hdr->fwdate[0] = ptm->tm_year % 100;
+ hdr->fwdate[1] = ptm->tm_mon + 1;
+ hdr->fwdate[2] = ptm->tm_mday;
+ hdr->fwvern[0] = v0;
+ hdr->fwvern[1] = v1;
+ hdr->fwvern[2] = v2;
+ memcpy(hdr->id, CODE_ID, strlen(CODE_ID));
+
+ off = sizeof(struct code_header);
+
+ fprintf(stderr, "writing firmware v%d.%d.%d on %d/%d/%d (y/m/d)\n",
+ v0, v1, v2,
+ hdr->fwdate[0], hdr->fwdate[1], hdr->fwdate[2]);
+
+
+ while ((n = fread(buf + off, 1, sizeof(buf)-off, in) + off) > 0) {
+ off = 0;
+ if (n < sizeof(buf)) {
+ if (ferror(in)) {
+ FREAD_ERROR:
+ fprintf(stderr, "fread error\n");
+ return EXIT_FAILURE;
+ }
+ if (gflag) {
+ gflag = sizeof(buf) - n;
+ memset(buf + n, 0xff, gflag);
+ fprintf(stderr, "adding %d bytes of garbage\n", gflag);
+ n = sizeof(buf);
+ }
+ }
+ if (!fwrite(buf, n, 1, out)) {
+ FWRITE_ERROR:
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (ferror(in)) {
+ goto FREAD_ERROR;
+ }
+
+ if (fflush(out)) {
+ goto FWRITE_ERROR;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/airlink.c b/tools/firmware-utils/src/airlink.c
new file mode 100644
index 0000000..06c83a0
--- /dev/null
+++ b/tools/firmware-utils/src/airlink.c
@@ -0,0 +1,332 @@
+/*
+ * Thanks to Vassily Galinsky for this tool
+*****************************************************************************
+AIRLINK AR525W firmware image structure
+ -8:-5 Extended (httpd) header checksum - sum2
+ -4:-1 Extended (httpd) header magic - "ARRN" - 0x4e525241
+ 0: 3 Standard (tftpd) header magic - "GMTK" - 0x4b544d47
+ 4: 7 Standard (tftpd) header checksum - sum1
+ 8: b 0
+ c: f Size of compressed linux kernel
+ 10:13 Size of firmware image file with standard header
+ 14:17 Product code - 0x5
+ 18:1b Bootloader checksum - sum0
+ 1c:1f 0
+ 20: Compressed linux kernel
+ - Squashfs or jffs2 file system - kernel dependent - either 32 bytes or sector aligned
+*****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+
+typedef unsigned char uchar;
+
+uint32_t crctab[257] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+ 0
+};
+
+uint32_t header[] = {
+ 0x00000000, 0x4e525241,
+ 0x4b544d47, 0x00000000, 0x00000000, 0x000afd4a,
+ 0x00000000, 0x00000005, 0x00000000, 0x00000000
+};
+
+static int JFFS2 = 0;
+
+int generate_image(char *kname, char *fsname, char *fname, int EHDR)
+{
+ int i;
+ uint32_t lenk, lens;
+ uchar *bk, *bs;
+ int fkd, ffd, fsd;
+ fkd = open(kname, O_RDONLY);
+ ffd = creat(fname, 0644);
+ if ((fkd < 0) || (ffd < 0))
+ return -1;
+ if (fsname) {
+ fsd = open(fsname, O_RDONLY);
+ if (fsd < 0)
+ return -1;
+ }
+ lenk = lseek(fkd, 0, SEEK_END);
+ header[5] = lenk;
+ bk = (uchar *) mmap(NULL, lenk, PROT_READ, MAP_SHARED, fkd, 0);
+ if (bk == MAP_FAILED)
+ return -1;
+ if (fsname) {
+ lens = lseek(fsd, 0, SEEK_END);
+ bs = (uchar *) mmap(NULL, lens, PROT_READ, MAP_SHARED, fsd,
+ 0);
+ if (bs == MAP_FAILED)
+ return -1;
+ }
+ if (EHDR)
+ write(ffd, header, 0x28);
+ else
+ write(ffd, header + 2, 0x20);
+ write(ffd, bk, lenk);
+ lenk += 0x20;
+ if (!JFFS2) JFFS2 = 0x20;
+ printf("Padding header+kernel - 0x%x + 0x%x = 0x%x\n",
+ lenk, ((lenk - 1 + JFFS2) / JFFS2) * JFFS2 - lenk,
+ ((lenk - 1 + JFFS2) / JFFS2) * JFFS2);
+ for (i = 0; i < ((lenk - 1 + JFFS2) / JFFS2) * JFFS2 - lenk; i++)
+ write(ffd, header, 1);
+ if (fsname) {
+ write(ffd, bs, lens);
+ close(fsd);
+ }
+ close(ffd);
+ close(fkd);
+ return 0;
+}
+
+uint32_t crc32(uchar * buf, uint32_t len)
+{
+ register int i;
+ uint32_t sum;
+ register uint32_t s0;
+ s0 = ~0;
+ for (i = 0; i < len; i++) {
+ s0 = (s0 >> 8) ^ crctab[(uchar) (s0 & 0xFF) ^ buf[i]];
+ }
+ sum = ~s0;
+ return sum;
+}
+
+void usage(char *prog)
+{
+ printf("Usage: %s [-b 0/1] image_filename \n", prog);
+ printf(" update checksums for firmware file\n");
+ printf
+ ("Usage: %s [-b 0/1] [-j erasesize_in_kibytes] [-e] kernel filesystem image_filename \n",
+ prog);
+ printf(" generate firmware file and update checksums\n");
+ printf("--------------------------------------------------\n");
+ printf(" -e - generate header for web upload\n");
+ printf(" -b 0/1 - clear/update bootloader checksum\n");
+ printf(" -j erasesize_in_kibytes - generate header for jffs2 filesystem\n");
+}
+
+int main(int argc, char **argv)
+{
+ uchar b[0x400];
+ char EHDR = 0;
+ char BHDR = 0;
+ int c, fd;
+ extern char *optarg;
+ extern int optind, optopt;
+
+ while ((c = getopt(argc, argv, "b:ej:")) != -1) {
+ switch (c) {
+ case 'b':
+ if (optarg[0] == '1')
+ BHDR = 1;
+ break;
+ case 'e':
+ EHDR = 1;
+ break;
+ case 'j':
+ sscanf(optarg, "%i", &JFFS2);
+ JFFS2 *= 1024;
+ break;
+ case '?':
+ fprintf(stderr, "\nError: unknown arg %c\n\n\n",
+ optopt);
+ usage(argv[0]);
+ exit(-1);
+ }
+ }
+ if (((argc - optind) < 1) && ((argc - optind) > 3)) {
+ usage(argv[0]);
+ exit(-1);
+ }
+ if ((argc - optind) == 3)
+ if (generate_image
+ (argv[optind], argv[optind + 1], argv[optind + 2],
+ EHDR)) {
+ fprintf(stderr,
+ "\nError generating image file %s\n\n\n",
+ argv[argc - 1]);
+ usage(argv[0]);
+ exit(-1);
+ }
+ if ((argc - optind) == 2)
+ if (generate_image
+ (argv[optind], NULL, argv[optind + 1], EHDR)) {
+ fprintf(stderr,
+ "\nError generating image file %s\n\n\n",
+ argv[argc - 1]);
+ usage(argv[0]);
+ exit(-1);
+ }
+
+ fd = open(argv[argc - 1], O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "\nImage file not found %s\n\n\n",
+ argv[argc - 1]);
+ usage(argv[0]);
+ exit(-1);
+ }
+ long i, len = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+ uchar *buf = malloc(len);
+ read(fd, buf, len);
+ uint32_t sum, l0;
+ uint32_t MagicS = 0x474d544b;
+ uint32_t MagicE = 0x4152524e;
+ if (ntohl(*((uint32_t *) buf)) == MagicS) {
+ fprintf(stderr,
+ "Image without extra 8 bytes - Standard header\n");
+ buf[0x10] = len & 0xff;
+ buf[0x11] = (len >> 8) & 0xff;
+ buf[0x12] = (len >> 16) & 0xff;
+ buf[0x13] = (len >> 24) & 0xff;
+ lseek(fd, 0x10, SEEK_SET);
+ write(fd, buf + 0x10, 0x4);
+ EHDR = 0;
+ } else if ((ntohl(*((uint32_t *) (buf + 0x8))) == MagicS)
+ && ((ntohl(*((uint32_t *) (buf + 0x4))) == MagicE))) {
+ fprintf(stderr,
+ "Image with extra 8 bytes - Extended header\n");
+ *((uint32_t *) (buf + 0x18)) = len - 8;
+ buf[0x18] = (len - 8) & 0xff;
+ buf[0x19] = ((len - 8) >> 8) & 0xff;
+ buf[0x1a] = ((len - 8) >> 16) & 0xff;
+ buf[0x1b] = ((len - 8) >> 24) & 0xff;
+ lseek(fd, 0x18, SEEK_SET);
+ write(fd, buf + 0x18, 0x4);
+ buf += 8;
+ EHDR = 1;
+ } else if (len == buf[0x10] | ((uint32_t)buf[0x11] << 8) | ((uint32_t)buf[0x12] << 16) | ((uint32_t)buf[0x13] << 24)) {
+ fprintf(stderr,
+ "Image without extra 8 bytes - Standard header\n");
+ EHDR = 0;
+ } else if (len == (buf[0x18] | ((uint32_t)buf[0x19] << 8) | ((uint32_t)buf[0x1a] << 16) | ((uint32_t)buf[0x1b] << 24)) + 8) {
+ fprintf(stderr,
+ "Image with extra 8 bytes - Extended header\n");
+ buf += 8;
+ EHDR = 1;
+ } else {
+ fprintf(stderr, "ERROR: Wrong image size\n");
+ exit(-1);
+ }
+ l0 = buf[0x10] | ((uint32_t)buf[0x11] << 8) | ((uint32_t)buf[0x12] << 16) | ((uint32_t)buf[0x13] << 24);
+ if (!BHDR)
+ *((uint32_t *) & buf[0x18]) = 0;
+ unsigned long sum0 = buf[0x18] | ((uint32_t)buf[0x19] << 8) | ((uint32_t)buf[0x1a] << 16) | ((uint32_t)buf[0x1b] << 24);
+ unsigned long sum1 = buf[0x4] | ((uint32_t)buf[0x5] << 8) | ((uint32_t)buf[0x6] << 16) | ((uint32_t)buf[0x7] << 24);
+ *((uint32_t *) & buf[0x4]) = 0x0L;
+ memcpy(b, buf, 0x100);
+ memcpy(b + 0x100, buf + ((l0 >> 1) - ((l0 & 0x6) >> 1)), 0x100);
+ memcpy(b + 0x200, buf + (l0 - 0x200), 0x200);
+ *((uint32_t *) & b[0x18]) = 0x0L;
+
+ sum = crc32(b, 0x400);
+ printf("CRC32 sum0 - (%x, %lx, %x)\n", sum, sum0, 0x400);
+ if (EHDR)
+ lseek(fd, 0x20, SEEK_SET);
+ else
+ lseek(fd, 0x18, SEEK_SET);
+ buf[0x18] = (BHDR ? sum : sum0) & 0xff;
+ buf[0x19] = ((BHDR ? sum : sum0) >> 8) & 0xff;
+ buf[0x1a] = ((BHDR ? sum : sum0) >> 16) & 0xff;
+ buf[0x1b] = ((BHDR ? sum : sum0) >> 24) & 0xff;
+ write(fd, &buf[0x18], 0x4);
+
+ sum = crc32(buf, l0);
+ printf("CRC32 sum1 - (%x, %lx, %x)\n", sum, sum1, l0);
+ if (EHDR)
+ lseek(fd, 0xC, SEEK_SET);
+ else
+ lseek(fd, 0x4, SEEK_SET);
+ buf[0x4] = sum & 0xff;
+ buf[0x5] = (sum >> 8) & 0xff;
+ buf[0x6] = (sum >> 16) & 0xff;
+ buf[0x7] = (sum >> 24) & 0xff;
+ write(fd, &buf[0x4], 0x4);
+ if (EHDR) {
+ unsigned long sum2 = buf[-0x8] | ((uint32_t)buf[-0x7] << 8) | ((uint32_t)buf[-0x6] << 16) | ((uint32_t)buf[-0x5] << 24);
+ *((uint32_t *) & buf[-0x8]) = 0L;
+ sum = crc32(buf - 0x4, len - 0x4);
+ printf("CRC32 sum2 - (%x, %lx, %lx)\n", sum, sum2,
+ len - 0x4);
+ lseek(fd, 0, SEEK_SET);
+ *((uint32_t *) & buf[-0x8]) = htonl(sum);
+ write(fd, &buf[-0x8], 0x4);
+ buf -= 8;
+ }
+ close(fd);
+ free(buf);
+ return 0;
+}
diff --git a/tools/firmware-utils/src/asustrx.c b/tools/firmware-utils/src/asustrx.c
new file mode 100644
index 0000000..67f2680
--- /dev/null
+++ b/tools/firmware-utils/src/asustrx.c
@@ -0,0 +1,256 @@
+/*
+ * asustrx
+ *
+ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * 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.
+ */
+
+#include <byteswap.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_le32(x) bswap_32(x)
+#define le32_to_cpu(x) bswap_32(x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_le32(x) (x)
+#define le32_to_cpu(x) (x)
+#else
+#error "Unsupported endianness"
+#endif
+
+#define TRX_MAGIC 0x30524448
+#define TRX_FLAGS_OFFSET 12
+
+struct trx_header {
+ uint32_t magic;
+ uint32_t length;
+ uint32_t crc32;
+ uint16_t flags;
+ uint16_t version;
+ uint32_t offset[3];
+};
+
+struct asustrx_tail {
+ uint8_t version[4];
+ char productid[12];
+ uint8_t unused[48];
+};
+
+char *in_path = NULL;
+char *out_path = NULL;
+char *productid = NULL;
+uint8_t version[4] = { };
+
+static const uint32_t crc32_tbl[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static void parse_options(int argc, char **argv) {
+ int c;
+
+ while ((c = getopt(argc, argv, "i:o:p:v:")) != -1) {
+ switch (c) {
+ case 'i':
+ in_path = optarg;
+ break;
+ case 'o':
+ out_path = optarg;
+ break;
+ case 'p':
+ productid = optarg;
+ break;
+ case 'v':
+ if (sscanf(optarg, "%hu.%hu.%hu.%hu", &version[0], &version[1], &version[2], &version[3]) != 4)
+ fprintf(stderr, "Version %s doesn't match suppored 4-digits format\n", optarg);
+ break;
+ }
+ }
+}
+
+static void usage() {
+ printf("Usage:\n");
+ printf("\t-i file\t\t\t\tinput TRX file\n");
+ printf("\t-o file\t\t\t\toutput Asus TRX file\n");
+ printf("\t-p productid\t\t\tproduct (device) ID\n");
+ printf("\t-v version\t\t\tfirmware version formatted with 4 digits like: 1.2.3.4\n");
+}
+
+int main(int argc, char **argv) {
+ struct trx_header hdr;
+ struct asustrx_tail tail = { };
+ FILE *in, *out;
+ uint8_t buf[1024];
+ size_t bytes;
+ size_t length = 0;
+ uint32_t crc32 = 0xffffffff;
+ int i;
+ int err = 0;
+
+ /* Parse & validate arguments */
+ parse_options(argc, argv);
+ if (!in_path || !out_path || !productid) {
+ usage();
+ err = -EINVAL;
+ goto err;
+ }
+
+ /* Fill Asus tail */
+ tail.version[0] = version[0];
+ tail.version[1] = version[1];
+ tail.version[2] = version[2];
+ tail.version[3] = version[3];
+ strncpy(tail.productid, productid, sizeof(tail.productid));
+
+ /* Open files */
+ in = fopen(in_path, "r");
+ if (!in) {
+ fprintf(stderr, "Couldn't open %s\n", in_path);
+ err = -EIO;
+ goto err;
+ }
+ out = fopen(out_path, "w+");
+ if (!out) {
+ fprintf(stderr, "Couldn't open %s\n", out_path);
+ err = -EIO;
+ goto err;
+ }
+
+ /* Check is there is empty place for Asus tail */
+ bytes = sizeof(struct asustrx_tail);
+ fseek(in, -bytes, SEEK_END);
+ if (fread(buf, 1, bytes, in) != bytes) {
+ fprintf(stderr, "Couldn't read %zu B from %s\n", bytes, in_path);
+ err = -EIO;
+ goto err;
+ }
+ for (i = 0; i < bytes; i++) {
+ if (buf[i]) {
+ fprintf(stderr, "Input TRX doesn't have last 64 B empty %s\n", out_path);
+ err = -ENOSPC;
+ goto err;
+ }
+ }
+
+ /* Copy whole TRX */
+ rewind(in);
+ while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
+ if (fwrite(buf, 1, bytes, out) != bytes) {
+ fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
+ err = -EIO;
+ goto err;
+ }
+ }
+
+ /* Overwrite last 64 B with Asus tail */
+ bytes = sizeof(tail);
+ fseek(out, -bytes, SEEK_CUR);
+ if (fwrite(&tail, 1, bytes, out) != bytes) {
+ fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
+ err = -EIO;
+ goto err;
+ }
+
+ /* Calculate crc32 */
+ fseek(out, TRX_FLAGS_OFFSET, SEEK_SET);
+ length = TRX_FLAGS_OFFSET;
+ while ((bytes = fread(buf, 1, sizeof(buf), out )) > 0) {
+ length += bytes;
+ for (i = 0; i < bytes; i++)
+ crc32 = crc32_tbl[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
+ }
+
+ /* Update header */
+ bytes = sizeof(hdr);
+ rewind(out);
+ if (fread(&hdr, 1, sizeof(hdr), out) != bytes) {
+ fprintf(stderr, "Couldn't read %zu B from %s\n", bytes, in_path);
+ err = -EIO;
+ goto err;
+ }
+ hdr.crc32 = cpu_to_le32(crc32);
+ rewind(out);
+ if (fwrite(&hdr, 1, bytes, out) != bytes) {
+ fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
+ err = -EIO;
+ goto err;
+ }
+
+err:
+ if (out)
+ fclose(out);
+ if (in)
+ fclose(in);
+ return err;
+}
diff --git a/tools/firmware-utils/src/bcm_tag.h b/tools/firmware-utils/src/bcm_tag.h
new file mode 100644
index 0000000..2730edc
--- /dev/null
+++ b/tools/firmware-utils/src/bcm_tag.h
@@ -0,0 +1,70 @@
+#ifndef __BCM63XX_TAG_H
+#define __BCM63XX_TAG_H
+
+#define TAGVER_LEN 4 /* Length of Tag Version */
+#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
+#define SIG1_LEN 20 /* Company Signature 1 Length */
+#define SIG2_LEN 14 /* Company Signature 2 Lenght */
+#define BOARDID_LEN 16 /* Length of BoardId */
+#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
+#define CHIPID_LEN 6 /* Chip Id Length */
+#define IMAGE_LEN 10 /* Length of Length Field */
+#define ADDRESS_LEN 12 /* Length of Address field */
+#define DUALFLAG_LEN 2 /* Dual Image flag Length */
+#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
+#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
+#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
+#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
+#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
+#define CRC_LEN 4 /* Length of CRC in bytes */
+#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
+
+#define NUM_PIRELLI 2
+#define IMAGETAG_CRC_START 0xFFFFFFFF
+
+#define PIRELLI_BOARDS { \
+ "AGPF-S0", \
+ "DWV-S0", \
+}
+
+/*
+ * The broadcom firmware assumes the rootfs starts the image,
+ * therefore uses the rootfs start (flashImageAddress)
+ * to determine where to flash the image. Since we have the kernel first
+ * we have to give it the kernel address, but the crc uses the length
+ * associated with this address (rootLength), which is added to the kernel
+ * length (kernelLength) to determine the length of image to flash and thus
+ * needs to be rootfs + deadcode (jffs2 EOF marker)
+*/
+
+struct bcm_tag {
+ char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
+ char sig_1[SIG1_LEN]; // 4-23: Company Line 1
+ char sig_2[SIG2_LEN]; // 24-37: Company Line 2
+ char chipid[CHIPID_LEN]; // 38-43: Chip this image is for
+ char boardid[BOARDID_LEN]; // 44-59: Board name
+ char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE
+ char totalLength[IMAGE_LEN]; // 62-71: Total length of image
+ char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
+ char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
+ char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware)
+ char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing
+ char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
+ char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
+ char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present
+ char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present
+ char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this)
+ char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT)
+ char flashLayoutVer[FLASHLAYOUTVER_LEN];// 192-195: Version flash layout
+ char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32
+ char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information
+ char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate)
+ char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition
+ char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition
+ char imageSequence[4]; // 228-231: Image sequence number
+ char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot
+ char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion
+ char reserved2[16]; // 240-255: Unused at present
+};
+
+#endif /* __BCM63XX_TAG_H */
diff --git a/tools/firmware-utils/src/bcmalgo.c b/tools/firmware-utils/src/bcmalgo.c
new file mode 100644
index 0000000..e7d3b11
--- /dev/null
+++ b/tools/firmware-utils/src/bcmalgo.c
@@ -0,0 +1,248 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include "bcmalgo.h"
+
+
+#define UTIL_VERSION "0.1"
+#define ENDIAN_REVERSE_NEEDED
+
+uint32_t reverse_endian32 ( uint32_t data )
+{
+#ifdef ENDIAN_REVERSE_NEEDED
+ return 0 | ( data & 0x000000ff ) << 24
+ | ( data & 0x0000ff00 ) << 8
+ | ( data & 0x00ff0000 ) >> 8
+ | ( data & 0xff000000 ) >> 24;
+#else
+ return data;
+#endif
+}
+
+uint16_t reverse_endian16 ( uint16_t data )
+{
+#ifdef ENDIAN_REVERSE_NEEDED
+ return 0 | ( data & 0x00ff ) << 8
+ | ( data & 0xff00 ) >> 8;
+#else
+ return data;
+#endif
+}
+
+
+
+uint32_t get_buffer_crc ( char* filebuffer,size_t size )
+{
+
+ long crc=0xffffffffL;
+ long crcxor = 0xffffffffL;
+ long num4 = 0xffffffffL;
+ long num5 = size;
+ long num6 = 0x4c11db7L;
+ long num7 = 0x80000000L;
+ int i;
+ long j;
+ for ( i = 0; i < ( num5 ); i++ )
+ {
+ long num2 = filebuffer[i];
+ for ( j = 0x80L; j != 0L; j = j >> 1 )
+ {
+ long num3 = crc & num7;
+ crc = crc << 1;
+ if ( ( num2 & j ) != 0L )
+ {
+ num3 ^= num7;
+ }
+ if ( num3 != 0L )
+ {
+ crc ^= num6;
+ }
+ }
+ }
+ crc ^= crcxor;
+ crc &= num4;
+
+ uint8_t b1 = ( uint8_t ) ( ( crc & -16777216L ) >> 0x18 );
+ uint8_t b2 = ( uint8_t ) ( ( crc & 0xff0000L ) >> 0x10 );
+ uint8_t b3 = ( uint8_t ) ( ( crc & 0xff00L ) >> 8 );
+ uint8_t b4 = ( uint8_t ) ( crc & 0xffL );
+ int32_t crc_result = ( b1 | b2 << 8| b3 << 16| b4 <<24 );
+ return reverse_endian32 ( crc_result );
+}
+
+//Thnx to Vector for the algo.
+uint32_t get_file_crc ( char* filename )
+{
+ struct stat buf;
+ stat ( filename,&buf );
+ char* filebuffer = malloc ( buf.st_size+10 );
+ FILE* fd = fopen ( filename,"r" );
+ fread ( filebuffer, 1, buf.st_size,fd );
+ fclose ( fd );
+ uint32_t crc = get_buffer_crc ( filebuffer,buf.st_size );
+ free ( filebuffer );
+ return crc;
+}
+
+
+
+uint16_t get_hcs ( ldr_header_t* hd )
+{
+ uint8_t* head = ( uint8_t* ) hd;
+ uint8_t hcs_minor;
+ uint8_t hcs_major;
+ uint16_t n = 0xffff;
+ uint16_t m = 0;
+ int state = 0;
+ int i,j;
+ for ( i = 0; i < 0x54; i++ )
+ {
+ uint16_t m = head[i];
+ m = m << 8;
+ for ( j = 0; j < 8; j++ )
+ {
+ if ( ( ( n ^ m ) & 0x8000 ) == 0 )
+ {
+ state = 0;
+ }
+ else
+ {
+ state = 1;
+ }
+ n = n << 1;
+ if ( state )
+ {
+ n ^= 0x1021;
+ }
+ m = m << 1;
+ }
+ n &= 0xffff;
+ }
+ n ^= 0xffff;
+ hcs_major = ( uint8_t ) ( ( n & 0xff00 ) >> 8 );
+ hcs_minor = ( uint8_t ) ( n & 0xff );
+ uint16_t hcs = hcs_major <<8 | hcs_minor;
+ return hcs;
+}
+
+ldr_header_t* construct_header ( uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc_data )
+{
+ ldr_header_t* hd = malloc ( sizeof ( ldr_header_t ) );
+ hd->magic=reverse_endian16 ( magic );
+ hd->control=0; //FixMe: Make use of it once compression is around
+ hd->rev_min = reverse_endian16 ( rev_min );
+ hd->rev_maj = reverse_endian16 ( rev_maj );
+ hd->build_date = reverse_endian32 ( build_date );
+ hd->filelen = reverse_endian32 ( filelen );
+ hd->ldaddress = reverse_endian32 ( ldaddress );
+ printf ( "Creating header for %s...\n", filename );
+ if ( strlen ( filename ) >63 )
+ {
+ printf ( "[!] Filename too long - stripping it to 63 bytes.\n" );
+ strncpy ( ( char* ) &hd->filename, filename, 63 );
+ hd->filename[63]=0x00;
+ }
+ else
+ {
+ strcpy ( ( char* ) &hd->filename, filename );
+ }
+ hd->crc=reverse_endian32 ( crc_data );
+ hd->hcs = reverse_endian16 ( get_hcs ( hd ) );
+ return hd;
+}
+
+static char control_unc[] = "Uncompressed";
+static char control_lz[] = "LZRW1/KH";
+static char control_mlzo[] = "mini-LZO";
+static char control_nrv[] = "NRV2D99 [Bootloader?]";
+static char control_nstdlzma[] = "(non-standard) LZMA";
+static char control_unk[] = "Unknown";
+char* get_control_info ( uint16_t control )
+{
+ control = reverse_endian16 ( control );
+ switch ( control )
+ {
+ case 0:
+ return control_unc;
+ break;
+ case 1:
+ return control_lz;
+ break;
+ case 2:
+ return control_mlzo;
+ break;
+ case 3:
+ return control_unc;
+ break;
+ case 4:
+ return control_nrv;
+ break;
+ case 5:
+ return control_nstdlzma;
+ break;
+ case 6:
+ return control_unc;
+ break;
+ case 7:
+ return control_unc;
+ break;
+ default:
+ return control_unk;
+ break;
+ }
+
+}
+
+int dump_header ( ldr_header_t* hd )
+{
+ printf ( "=== Header Information ===\n" );
+ printf ( "Header magic:\t0x%04X\n",reverse_endian16 ( hd->magic ) );
+ printf ( "Control:\t0x%04X (%s)\n",reverse_endian16 ( hd->control ), get_control_info ( hd->control ) );
+ printf ( "Major rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_maj ) );
+ printf ( "Minor rev. :\t0x%04X\n",reverse_endian16 ( hd->rev_min ) );
+ printf ( "File name :\t%s\n", ( char* ) &hd->filename );
+ printf ( "File length:\t%d bytes\n", reverse_endian32 ( hd->filelen ) );
+ printf ( "Build time:\t0x%08X //FixMe: print in human-readable form\n", reverse_endian32 ( hd->build_date ) ); //FixMe:
+ printf ( "HCS:\t\t0x%04X ",reverse_endian16 ( hd->hcs ) );
+ uint16_t hcs = get_hcs ( hd );
+ int ret=0;
+ if ( hcs ==reverse_endian16 ( hd->hcs ) )
+ {
+ printf ( "(OK!)\n" );
+ }
+ else
+ {
+ printf ( "(ERROR! expected 0x%04X)\n",hcs );
+ ret=1;
+ }
+//printf("HCS:\t0x%02X",reverse_endian32(hd->hcs));
+ printf ( "Load address:\t0x%08X\n", reverse_endian32 ( hd->ldaddress ) ); //FixMe:
+ printf ( "HNW:\t\t0x%04X\n",reverse_endian16 ( hd->her_znaet_chto ) ); //Hell knows what
+ printf ( "CRC:\t\t0x%08X\n",reverse_endian32 ( hd->crc ) );
+ printf ( "=== Binary Header Dump===\n" );
+ int i,j;
+ uint8_t* head = ( uint8_t* ) hd;
+ for ( i=0;i<=sizeof ( ldr_header_t );i++ )
+ {
+ if ( i % 8==0 )
+ printf ( "\n" );
+ printf ( "0x%02x ",head[i] );
+ }
+ printf ( "\n\n== End Of Header dump ==\n" );
+ return ret;
+}
+
+
+void print_copyright()
+{
+ printf ( "Part of bcm-utils package ver. " UTIL_VERSION " \n" );
+ printf ( "Copyright (C) 2009 Andrew 'Necromant' Andrianov\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions. See COPYING for details\n" );
+}
diff --git a/tools/firmware-utils/src/bcmalgo.h b/tools/firmware-utils/src/bcmalgo.h
new file mode 100644
index 0000000..46647cf
--- /dev/null
+++ b/tools/firmware-utils/src/bcmalgo.h
@@ -0,0 +1,83 @@
+#ifndef bcmutils_H
+#define bcmutils_H
+
+typedef struct
+{
+ uint16_t magic;
+ uint16_t control;
+ uint16_t rev_maj;
+ uint16_t rev_min;
+ uint32_t build_date;
+ uint32_t filelen;
+ uint32_t ldaddress;
+ char filename[64];
+ uint16_t hcs;
+ uint16_t her_znaet_chto; //v dushe ne ebu
+ uint32_t crc;
+} ldr_header_t;
+
+
+/**
+ * Reverses endianess of a 32bit int, if the ENDIAN_REVERSE_NEEDED defined at compile-time
+ * @param data
+ * @return
+ */
+uint32_t reverse_endian32 ( uint32_t data );
+
+/**
+ * Reverses endianess of a 16bit int, if the ENDIAN_REVERSE_NEEDED defined at compile-time
+ * @param data
+ * @return
+ */
+uint16_t reverse_endian16 ( uint16_t data );
+/**
+ * Calculates the strange crc (used by bcm modems) of the file. Thnx fly out to Vector for the algorithm.
+ * @param filename
+ * @return
+ */
+uint32_t get_file_crc ( char* filename );
+
+/**
+ * Calculates HCS of the header.
+ * @param hd
+ * @return
+ */
+uint16_t get_hcs ( ldr_header_t* hd );
+
+/**
+ * Constructs the header of the image with the information given It also automagically calculates HCS and writes it there.
+ * @param magic - magic device bytes
+ * @param rev_maj - major revision
+ * @param rev_min - minor revision
+ * @param build_date - build date (seconds from EPOCH UTC)
+ * @param filelen - file length in bytes
+ * @param ldaddress - Load adress
+ * @param filename - filename
+ * @param crc_data - the crc of the data
+ * @return
+ */
+ldr_header_t* construct_header ( uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc_data );
+
+/**
+ * Dumps header information to stdout.
+ * @param hd
+ */
+int dump_header ( ldr_header_t* hd );
+
+
+/**
+ * Returns a null terminated string describing what the control number meens
+ * DO NOT FREE IT!!!
+ * @param control
+ * @return
+ */
+char* get_control_info ( uint16_t control );
+#endif
+
+/**
+ * Calculates bcmCRC of a data buffer.
+ * @param filebuffer - pointer to buffer
+ * @param size - buffer size
+ * @return
+ */
+uint32_t get_buffer_crc ( char* filebuffer, size_t size );
diff --git a/tools/firmware-utils/src/buffalo-enc.c b/tools/firmware-utils/src/buffalo-enc.c
new file mode 100644
index 0000000..794659e
--- /dev/null
+++ b/tools/firmware-utils/src/buffalo-enc.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+
+#include "buffalo-lib.h"
+
+#define ERR(fmt, args...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## args ); \
+} while (0)
+
+static char *progname;
+static char *ifname;
+static char *ofname;
+static char *crypt_key = "Buffalo";
+static char *magic = "start";
+static int longstate;
+static unsigned char seed = 'O';
+
+static char *product;
+static char *version;
+static int do_decrypt;
+static int offset;
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -d decrypt instead of encrypt\n"
+" -i <file> read input from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -l use longstate {en,de}cryption method\n"
+" -k <key> use <key> for encryption (default: Buffalo)\n"
+" -m <magic> set magic to <magic>\n"
+" -p <product> set product name to <product>\n"
+" -v <version> set version to <version>\n"
+" -h show this screen\n"
+" -O Offset of encrypted data in file (decryption)\n"
+ );
+
+ exit(status);
+}
+
+static int decrypt_file(void)
+{
+ struct enc_param ep;
+ ssize_t src_len;
+ unsigned char *buf = NULL;
+ int err;
+ int ret = -1;
+
+ src_len = get_file_size(ifname);
+ if (src_len < 0) {
+ ERR("unable to get size of '%s'", ifname);
+ goto out;
+ }
+
+ buf = malloc(src_len);
+ if (buf == NULL) {
+ ERR("no memory for the buffer");
+ goto out;
+ }
+
+ err = read_file_to_buf(ifname, buf, src_len);
+ if (err) {
+ ERR("unable to read from file '%s'", ifname);
+ goto out;
+ }
+
+ memset(&ep, '\0', sizeof(ep));
+ ep.key = (unsigned char *) crypt_key;
+ ep.longstate = longstate;
+
+ err = decrypt_buf(&ep, buf + offset, src_len - offset);
+ if (err) {
+ ERR("unable to decrypt '%s'", ifname);
+ goto out;
+ }
+
+ printf("Magic\t\t: '%s'\n", ep.magic);
+ printf("Seed\t\t: 0x%02x\n", ep.seed);
+ printf("Product\t\t: '%s'\n", ep.product);
+ printf("Version\t\t: '%s'\n", ep.version);
+ printf("Data len\t: %u\n", ep.datalen);
+ printf("Checksum\t: 0x%08x\n", ep.csum);
+
+ err = write_buf_to_file(ofname, buf + offset, ep.datalen);
+ if (err) {
+ ERR("unable to write to file '%s'", ofname);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ free(buf);
+ return ret;
+}
+
+static int encrypt_file(void)
+{
+ struct enc_param ep;
+ ssize_t src_len;
+ unsigned char *buf;
+ uint32_t hdrlen;
+ ssize_t totlen = 0;
+ int err;
+ int ret = -1;
+
+ src_len = get_file_size(ifname);
+ if (src_len < 0) {
+ ERR("unable to get size of '%s'", ifname);
+ goto out;
+ }
+
+ totlen = enc_compute_buf_len(product, version, src_len);
+ hdrlen = enc_compute_header_len(product, version);
+
+ buf = malloc(totlen);
+ if (buf == NULL) {
+ ERR("no memory for the buffer");
+ goto out;
+ }
+
+ err = read_file_to_buf(ifname, &buf[hdrlen], src_len);
+ if (err) {
+ ERR("unable to read from file '%s'", ofname);
+ goto free_buf;
+ }
+
+ memset(&ep, '\0', sizeof(ep));
+ ep.key = (unsigned char *) crypt_key;
+ ep.seed = seed;
+ ep.longstate = longstate;
+ ep.csum = buffalo_csum(src_len, &buf[hdrlen], src_len);
+ ep.datalen = src_len;
+ strcpy((char *) ep.magic, magic);
+ strcpy((char *) ep.product, product);
+ strcpy((char *) ep.version, version);
+
+ err = encrypt_buf(&ep, buf, &buf[hdrlen]);
+ if (err) {
+ ERR("invalid input file");
+ goto free_buf;
+ }
+
+ err = write_buf_to_file(ofname, buf, totlen);
+ if (err) {
+ ERR("unable to write to file '%s'", ofname);
+ goto free_buf;
+ }
+
+ ret = 0;
+
+free_buf:
+ free(buf);
+out:
+ return ret;
+}
+
+static int check_params(void)
+{
+ int ret = -1;
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto out;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto out;
+ }
+
+ if (crypt_key == NULL) {
+ ERR("no key specified");
+ goto out;
+ } else if (strlen(crypt_key) > BCRYPT_MAX_KEYLEN) {
+ ERR("key '%s' is too long", crypt_key);
+ goto out;
+ }
+
+ if (strlen(magic) != (ENC_MAGIC_LEN - 1)) {
+ ERR("length of magic must be %d", ENC_MAGIC_LEN - 1);
+ goto out;
+ }
+
+ if (!do_decrypt) {
+ if (product == NULL) {
+ ERR("no product specified");
+ goto out;
+ }
+
+ if (version == NULL) {
+ ERR("no version specified");
+ goto out;
+ }
+
+ if (strlen(product) > (ENC_PRODUCT_LEN - 1)) {
+ ERR("product name '%s' is too long", product);
+ goto out;
+ }
+
+ if (strlen(version) > (ENC_VERSION_LEN - 1)) {
+ ERR("version '%s' is too long", version);
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int res = EXIT_FAILURE;
+ int err;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "adi:m:o:hlp:v:k:O:r:s:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'd':
+ do_decrypt = 1;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'l':
+ longstate = 1;
+ break;
+ case 'm':
+ magic = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'p':
+ product = optarg;
+ break;
+ case 'v':
+ version = optarg;
+ break;
+ case 'k':
+ crypt_key = optarg;
+ break;
+ case 's':
+ seed = strtoul(optarg, NULL, 16);
+ break;
+ case 'O':
+ offset = strtoul(optarg, NULL, 0);
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ err = check_params();
+ if (err)
+ goto out;
+
+ if (do_decrypt)
+ err = decrypt_file();
+ else
+ err = encrypt_file();
+
+ if (err)
+ goto out;
+
+ res = EXIT_SUCCESS;
+
+out:
+ return res;
+}
diff --git a/tools/firmware-utils/src/buffalo-lib.c b/tools/firmware-utils/src/buffalo-lib.c
new file mode 100644
index 0000000..b1d5ede
--- /dev/null
+++ b/tools/firmware-utils/src/buffalo-lib.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "buffalo-lib.h"
+
+static uint32_t crc32_table[256] =
+{
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+ 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+ 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+ 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+ 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+ 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+ 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+ 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+ 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+ 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+ 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+ 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+ 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+ 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+ 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+ 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+ 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+ 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+ 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+ 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+ 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+ 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+ 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+ 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+ 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+ 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+ 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+ 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+ 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+ 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+ 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+ 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+ 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+ 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+ 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+int bcrypt_init(struct bcrypt_ctx *ctx, void *key, int keylen,
+ unsigned long state_len)
+{
+ unsigned char *state;
+ unsigned char *p = key;
+ unsigned long i, j;
+ unsigned long k = 0;
+
+ state = malloc(state_len);
+ if (state == NULL)
+ return -1;
+
+ ctx->i = 0;
+ ctx->j = 0;
+ ctx->state = state;
+ ctx->state_len = state_len;
+
+ for (i = 0; i < state_len; i++)
+ state[i] = i;
+
+ for(i = 0, j = 0; i < state_len; i++, j = (j + 1) % keylen) {
+ unsigned char t;
+
+ t = state[i];
+ k = (k + p[j] + t) % state_len;
+ state[i] = state[k];
+ state[k] = t;
+ }
+
+ return 0;
+}
+
+int bcrypt_process(struct bcrypt_ctx *ctx, unsigned char *src,
+ unsigned char *dst, unsigned long len)
+{
+ unsigned char *state = ctx->state;
+ unsigned long state_len = ctx->state_len;
+ unsigned char i, j;
+ unsigned long k;
+
+ i = ctx->i;
+ j = ctx->j;
+
+ for (k = 0; k < len; k++) {
+ unsigned char t;
+
+ i = (i + 1) % state_len;
+ j = (j + state[i]) % state_len;
+ t = state[j];
+ state[j] = state[i];
+ state[i] = t;
+
+ dst[k] = src[k] ^ state[(state[i] + state[j]) % state_len];
+ }
+
+ ctx->i = i;
+ ctx->j = j;
+
+ return len;
+}
+
+void bcrypt_finish(struct bcrypt_ctx *ctx)
+{
+ if (ctx->state)
+ free(ctx->state);
+}
+
+int bcrypt_buf(unsigned char seed, unsigned char *key, unsigned char *src,
+ unsigned char *dst, unsigned long len, int longstate)
+{
+ unsigned char bckey[BCRYPT_MAX_KEYLEN + 1];
+ unsigned int keylen;
+ struct bcrypt_ctx ctx;
+ int ret;
+
+ /* setup decryption key */
+ keylen = strlen((char *) key);
+ bckey[0] = seed;
+ memcpy(&bckey[1], key, keylen);
+
+ keylen++;
+
+ ret = bcrypt_init(&ctx, bckey, keylen,
+ (longstate) ? len : BCRYPT_DEFAULT_STATE_LEN);
+ if (ret)
+ return ret;
+
+ bcrypt_process(&ctx, src, dst, len);
+ bcrypt_finish(&ctx);
+
+ return 0;
+}
+
+uint32_t buffalo_csum(uint32_t csum, void *buf, unsigned long len)
+{
+ signed char *p = buf;
+
+ while (len--) {
+ int i;
+
+ csum ^= *p++;
+ for (i = 0; i < 8; i++)
+ csum = (csum >> 1) ^ ((csum & 1) ? 0xedb88320ul : 0);
+ }
+
+ return csum;
+}
+
+uint32_t buffalo_crc(void *buf, unsigned long len)
+{
+ unsigned char *p = buf;
+ unsigned long t = len;
+ uint32_t crc = 0;
+
+ while (len--)
+ crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *p++) & 0xFF];
+
+ while (t) {
+ crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ t) & 0xFF];
+ t >>= 8;
+ }
+
+ return ~crc;
+}
+
+unsigned long enc_compute_header_len(char *product, char *version)
+{
+ return ENC_MAGIC_LEN + 1 + strlen(product) + 1 +
+ strlen(version) + 1 + 3 * sizeof(uint32_t);
+}
+
+unsigned long enc_compute_buf_len(char *product, char *version,
+ unsigned long datalen)
+{
+ unsigned long ret;
+
+ ret = enc_compute_header_len(product, version);
+ ret += datalen + sizeof(uint32_t);
+ ret += (4 - ret % 4);
+
+ return ret;
+}
+
+static void put_be32(void *data, uint32_t val)
+{
+ unsigned char *p = data;
+
+ p[0] = (val >> 24) & 0xff;
+ p[1] = (val >> 16) & 0xff;
+ p[2] = (val >> 8) & 0xff;
+ p[3] = val & 0xff;
+}
+
+static uint32_t get_be32(void *data)
+{
+ unsigned char *p = data;
+
+ return (((uint32_t)p[0]) << 24) |
+ (((uint32_t)p[1]) << 16) |
+ (((uint32_t)p[2]) << 8) |
+ ((uint32_t)p[3]);
+}
+
+static int check_magic(void *magic)
+{
+ if (!memcmp("start", magic, ENC_MAGIC_LEN))
+ return 0;
+
+ if (!memcmp("asar1", magic, ENC_MAGIC_LEN))
+ return 0;
+
+ return -1;
+}
+
+int encrypt_buf(struct enc_param *ep, unsigned char *hdr,
+ unsigned char *data)
+{
+ unsigned char *p;
+ uint32_t len;
+ int err;
+ int ret = -1;
+ unsigned char s;
+
+ p = (unsigned char *) hdr;
+
+ /* setup magic */
+ len = strlen((char *) ep->magic) + 1;
+ memcpy(p, ep->magic, len);
+ p += len;
+
+ /* setup seed */
+ *p++ = ep->seed;
+
+ /* put product len */
+ len = strlen((char *) ep->product) + 1;
+ put_be32(p, len);
+ p += sizeof(uint32_t);
+
+ /* copy and crypt product name */
+ memcpy(p, ep->product, len);
+ err = bcrypt_buf(ep->seed, ep->key, p, p, len, ep->longstate);
+ if (err)
+ goto out;
+ s = *p;
+ p += len;
+
+ /* put version length */
+ len = strlen((char *) ep->version) + 1;
+ put_be32(p, len);
+ p += sizeof(uint32_t);
+
+ /* copy and crypt version */
+ memcpy(p, ep->version, len);
+ err = bcrypt_buf(s, ep->key, p, p, len, ep->longstate);
+ if (err)
+ goto out;
+ s = *p;
+ p += len;
+
+ /* put data length */
+ put_be32(p, ep->datalen);
+
+ /* encrypt data */
+ err = bcrypt_buf(s, ep->key, data, data, ep->datalen, ep->longstate);
+ if (err)
+ goto out;
+
+ /* put checksum */
+ put_be32(&data[ep->datalen], ep->csum);
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int decrypt_buf(struct enc_param *ep, unsigned char *data,
+ unsigned long datalen)
+{
+ unsigned char *p;
+ uint32_t prod_len;
+ uint32_t ver_len;
+ uint32_t len;
+ uint32_t csum;
+ ssize_t remain;
+ int err;
+ int ret = -1;
+
+#define CHECKLEN(_l) do { \
+ len = (_l); \
+ if (remain < len) { \
+ goto out; \
+ } \
+} while (0)
+
+#define INCP() do { \
+ p += len; \
+ remain -= len; \
+} while (0)
+
+ remain = datalen;
+ p = data;
+
+ CHECKLEN(ENC_MAGIC_LEN);
+ err = check_magic(p);
+ if (err)
+ goto out;
+ memcpy(ep->magic, p, ENC_MAGIC_LEN);
+ INCP();
+
+ CHECKLEN(1);
+ ep->seed = *p;
+ INCP();
+
+ CHECKLEN(sizeof(uint32_t));
+ prod_len = get_be32(p);
+ if (prod_len > ENC_PRODUCT_LEN)
+ goto out;
+ INCP();
+
+ CHECKLEN(prod_len);
+ memcpy(ep->product, p, prod_len);
+ INCP();
+
+ CHECKLEN(sizeof(uint32_t));
+ ver_len = get_be32(p);
+ if (ver_len > ENC_VERSION_LEN)
+ goto out;
+ INCP();
+
+ CHECKLEN(ver_len);
+ memcpy(ep->version, p, ver_len);
+ INCP();
+
+ CHECKLEN(sizeof(uint32_t));
+ ep->datalen = get_be32(p);
+ INCP();
+
+ /* decrypt data */
+ CHECKLEN(ep->datalen);
+ err = bcrypt_buf(ep->version[0], ep->key, p, data, ep->datalen,
+ ep->longstate);
+ if (err)
+ goto out;
+ INCP();
+
+ CHECKLEN(sizeof(uint32_t));
+ ep->csum = get_be32(p);
+ INCP();
+
+ csum = buffalo_csum(ep->datalen, data, ep->datalen);
+ if (csum != ep->csum)
+ goto out;
+
+ /* decrypt product name */
+ err = bcrypt_buf(ep->product[0], ep->key, ep->version, ep->version,
+ ver_len, ep->longstate);
+ if (err)
+ goto out;
+
+ /* decrypt version */
+ err = bcrypt_buf(ep->seed, ep->key, ep->product, ep->product, prod_len,
+ ep->longstate);
+ if (err)
+ goto out;
+
+ ret = 0;
+out:
+ return ret;
+
+#undef CHECKLEN
+#undef INCP
+}
+
+ssize_t get_file_size(char *name)
+{
+ struct stat st;
+ int err;
+
+ err = stat(name, &st);
+ if (err)
+ return -1;
+
+ return st.st_size;
+}
+
+int read_file_to_buf(char *name, void *buf, ssize_t buflen)
+{
+ FILE *f;
+ size_t done;
+ int ret = -1;
+
+ f = fopen(name, "r");
+ if (f == NULL)
+ goto out;
+
+ errno = 0;
+ done = fread(buf, buflen, 1, f);
+ if (done != 1)
+ goto close;
+
+ ret = 0;
+
+close:
+ fclose(f);
+out:
+ return ret;
+}
+
+int write_buf_to_file(char *name, void *buf, ssize_t buflen)
+{
+ FILE *f;
+ size_t done;
+ int ret = -1;
+
+ f = fopen(name, "w");
+ if (f == NULL)
+ goto out;
+
+ errno = 0;
+ done = fwrite(buf, buflen, 1, f);
+ if (done != 1)
+ goto close;
+
+ ret = 0;
+
+close:
+ fflush(f);
+ fclose(f);
+ if (ret)
+ unlink(name);
+out:
+ return ret;
+}
diff --git a/tools/firmware-utils/src/buffalo-lib.h b/tools/firmware-utils/src/buffalo-lib.h
new file mode 100644
index 0000000..ba8a508
--- /dev/null
+++ b/tools/firmware-utils/src/buffalo-lib.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#ifndef _BUFFALO_LIB_H
+#define _BUFFALO_LIB_H
+
+#include <stdint.h>
+
+#define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#define BIT(_x) (1UL << (_x))
+
+#define TAG_BRAND_LEN 32
+#define TAG_PRODUCT_LEN 32
+#define TAG_VERSION_LEN 8
+#define TAG_REGION_LEN 2
+#define TAG_LANGUAGE_LEN 8
+#define TAG_PLATFORM_LEN 8
+#define TAG_HWVER_LEN 4
+#define TAG_HWVER_VAL_LEN 4
+
+struct buffalo_tag {
+ unsigned char product[TAG_PRODUCT_LEN];
+ unsigned char brand[TAG_BRAND_LEN];
+ unsigned char ver_major[TAG_VERSION_LEN];
+ unsigned char ver_minor[TAG_VERSION_LEN];
+ unsigned char region_code[2];
+ uint32_t region_mask;
+ unsigned char unknown0[2];
+ unsigned char language[TAG_LANGUAGE_LEN];
+ unsigned char platform[TAG_PLATFORM_LEN];
+ unsigned char hwv[TAG_HWVER_LEN];
+ unsigned char hwv_val[TAG_HWVER_VAL_LEN];
+ uint8_t unknown1[24];
+
+ uint32_t len;
+ uint32_t crc;
+ uint32_t base1;
+ uint32_t base2;
+ uint32_t data_len;
+ uint8_t flag;
+ uint8_t unknown2[3];
+} __attribute ((packed));
+
+struct buffalo_tag2 {
+ unsigned char product[TAG_PRODUCT_LEN];
+ unsigned char brand[TAG_BRAND_LEN];
+ unsigned char ver_major[TAG_VERSION_LEN];
+ unsigned char ver_minor[TAG_VERSION_LEN];
+ unsigned char region_code[2];
+ uint32_t region_mask;
+ unsigned char unknown0[2];
+ unsigned char language[TAG_LANGUAGE_LEN];
+ unsigned char platform[TAG_PLATFORM_LEN];
+ unsigned char hwv[TAG_HWVER_LEN];
+ unsigned char hwv_val[TAG_HWVER_VAL_LEN];
+ uint8_t unknown1[24];
+
+ uint32_t total_len;
+ uint32_t crc;
+ uint32_t len1;
+ uint32_t len2;
+ uint8_t flag;
+ uint8_t unknown2[3];
+} __attribute ((packed));
+
+#define ENC_PRODUCT_LEN 32
+#define ENC_VERSION_LEN 8
+#define ENC_MAGIC_LEN 6
+
+unsigned long enc_compute_header_len(char *product, char *version);
+unsigned long enc_compute_buf_len(char *product, char *version,
+ unsigned long datalen);
+
+struct enc_param {
+ unsigned char *key;
+ unsigned char magic[ENC_MAGIC_LEN];
+ unsigned char product[ENC_PRODUCT_LEN];
+ unsigned char version[ENC_VERSION_LEN];
+ unsigned char seed;
+ int longstate;
+ unsigned datalen;
+ uint32_t csum;
+};
+
+int encrypt_buf(struct enc_param *ep, unsigned char *hdr,
+ unsigned char *data);
+int decrypt_buf(struct enc_param *ep, unsigned char *data,
+ unsigned long datalen);
+
+#define BCRYPT_DEFAULT_STATE_LEN 256
+#define BCRYPT_MAX_KEYLEN 254
+
+struct bcrypt_ctx {
+ unsigned long i;
+ unsigned long j;
+ unsigned char *state;
+ unsigned long state_len;
+};
+
+int bcrypt_init(struct bcrypt_ctx *ctx, void *key, int keylen,
+ unsigned long state_len);
+int bcrypt_process(struct bcrypt_ctx *ctx, unsigned char *src,
+ unsigned char *dst, unsigned long len);
+void bcrypt_finish(struct bcrypt_ctx *ctx);
+int bcrypt_buf(unsigned char seed, unsigned char *key, unsigned char *src,
+ unsigned char *dst, unsigned long len, int longstate);
+
+uint32_t buffalo_csum(uint32_t csum, void *buf, unsigned long len);
+uint32_t buffalo_crc(void *buf, unsigned long len);
+
+ssize_t get_file_size(char *name);
+int read_file_to_buf(char *name, void *buf, ssize_t buflen);
+int write_buf_to_file(char *name, void *buf, ssize_t buflen);
+
+#endif /* _BUFFALO_LIB_H */
diff --git a/tools/firmware-utils/src/buffalo-tag.c b/tools/firmware-utils/src/buffalo-tag.c
new file mode 100644
index 0000000..b5db72e
--- /dev/null
+++ b/tools/firmware-utils/src/buffalo-tag.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <netinet/in.h>
+
+#include "buffalo-lib.h"
+
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static char *region_table[] = {
+ "JP", "US", "EU", "AP", "TW", "KR"
+};
+
+#define MAX_INPUT_FILES 2
+
+static char *progname;
+static char *ifname[MAX_INPUT_FILES];
+static ssize_t fsize[MAX_INPUT_FILES];
+static int num_files;
+static char *ofname;
+static char *product;
+static char *brand;
+static char *language;
+static char *hwver;
+static char *platform;
+static int flag;
+static char *major;
+static char *minor = "1.01";
+static int skipcrc;
+static uint32_t base1;
+static uint32_t base2;
+static char *region_code;
+static uint32_t region_mask;
+static int num_regions;
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -a <platform> set platform to <platform>\n"
+" -b <brand> set brand to <brand>\n"
+" -c <base1>\n"
+" -d <base2>\n"
+" -f <flag> set flag to <flag>\n"
+" -i <file> read input from the file <file>\n"
+" -l <language> set language to <language>\n"
+" -m <version> set minor version to <version>\n"
+" -o <file> write output to the file <file>\n"
+" -p <product> set product to <product>\n"
+" -r <region> set image region to <region>\n"
+" valid regions: JP, US, EU, AP, TW, KR, M_\n"
+" -s skip CRC calculation\n"
+" -v <version> set major version to <version>\n"
+" -w <version> set harwdware version to <version>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static int check_params(void)
+{
+
+#define CHECKSTR(_var, _name, _len) do { \
+ if ((_var) == NULL) { \
+ ERR("no %s specified", (_name)); \
+ return -1; \
+ } \
+ if ((_len) > 0 && \
+ strlen((_var)) > ((_len) - 1)) { \
+ ERR("%s is too long", (_name)); \
+ return -1; \
+ } \
+} while (0)
+
+ if (num_files == 0)
+ ERR("no input files specified");
+
+ CHECKSTR(ofname, "output file", 0);
+ CHECKSTR(brand, "brand", TAG_BRAND_LEN);
+ CHECKSTR(product, "product", TAG_PRODUCT_LEN);
+ CHECKSTR(platform, "platform", TAG_PLATFORM_LEN);
+ CHECKSTR(major, "major version", TAG_VERSION_LEN);
+ CHECKSTR(minor, "minor version", TAG_VERSION_LEN);
+ CHECKSTR(language, "language", TAG_LANGUAGE_LEN);
+
+ if (hwver)
+ CHECKSTR(hwver, "hardware version", 2);
+
+ if (num_regions == 0) {
+ ERR("no region code specified");
+ return -1;
+ }
+
+ return 0;
+
+#undef CHECKSTR
+}
+
+static int process_region(char *reg)
+{
+ int i;
+
+ if (strlen(reg) != 2) {
+ ERR("invalid region code '%s'", reg);
+ return -1;
+ }
+
+ if (strcmp(reg, "M_") == 0) {
+ region_code = reg;
+ region_mask |= ~0;
+ num_regions = 32;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(region_table); i++)
+ if (strcmp(reg, region_table[i]) == 0) {
+ region_code = reg;
+ region_mask |= 1 << i;
+ num_regions++;
+ return 0;
+ }
+
+ ERR("unknown region code '%s'", reg);
+ return -1;
+}
+
+static int process_ifname(char *name)
+{
+ if (num_files >= ARRAY_SIZE(ifname)) {
+ ERR("too many input files specified");
+ return -1;
+ }
+
+ ifname[num_files++] = name;
+ return 0;
+}
+
+static void fixup_tag(unsigned char *buf, ssize_t buflen)
+{
+ struct buffalo_tag *tag = (struct buffalo_tag *) buf;
+
+ memset(tag, '\0', sizeof(*tag));
+
+ memcpy(tag->brand, brand, strlen(brand));
+ memcpy(tag->product, product, strlen(product));
+ memcpy(tag->platform, platform, strlen(platform));
+ memcpy(tag->ver_major, major, strlen(major));
+ memcpy(tag->ver_minor, minor, strlen(minor));
+ memcpy(tag->language, language, strlen(language));
+
+ if (num_regions > 1) {
+ tag->region_code[0] = 'M';
+ tag->region_code[1] = '_';
+ tag->region_mask = htonl(region_mask);
+ } else {
+ memcpy(tag->region_code, region_code, 2);
+ }
+
+ tag->len = htonl(buflen);
+ tag->data_len = htonl(fsize[0]);
+ tag->base1 = htonl(base1);
+ tag->base2 = htonl(base2);
+ tag->flag = flag;
+
+ if (hwver) {
+ memcpy(tag->hwv, "hwv", 3);
+ memcpy(tag->hwv_val, hwver, strlen(hwver));
+ }
+
+ if (!skipcrc)
+ tag->crc = htonl(buffalo_crc(buf, buflen));
+}
+
+static void fixup_tag2(unsigned char *buf, ssize_t buflen)
+{
+ struct buffalo_tag2 *tag = (struct buffalo_tag2 *) buf;
+
+ memset(tag, '\0', sizeof(*tag));
+
+ memcpy(tag->brand, brand, strlen(brand));
+ memcpy(tag->product, product, strlen(product));
+ memcpy(tag->platform, platform, strlen(platform));
+ memcpy(tag->ver_major, major, strlen(major));
+ memcpy(tag->ver_minor, minor, strlen(minor));
+ memcpy(tag->language, language, strlen(language));
+
+ if (num_regions > 1) {
+ tag->region_code[0] = 'M';
+ tag->region_code[1] = '_';
+ tag->region_mask = htonl(region_mask);
+ } else {
+ memcpy(tag->region_code, region_code, 2);
+ }
+
+ tag->total_len = htonl(buflen);
+ tag->len1 = htonl(fsize[0]);
+ tag->len2 = htonl(fsize[1]);
+ tag->flag = flag;
+
+ if (hwver) {
+ memcpy(tag->hwv, "hwv", 3);
+ memcpy(tag->hwv_val, hwver, strlen(hwver));
+ }
+
+ if (!skipcrc)
+ tag->crc = htonl(buffalo_crc(buf, buflen));
+}
+
+static int tag_file(void)
+{
+ unsigned char *buf;
+ ssize_t offset;
+ ssize_t hdrlen;
+ ssize_t buflen;
+ int err;
+ int ret = -1;
+ int i;
+
+ if (num_files == 1)
+ hdrlen = sizeof(struct buffalo_tag);
+ else
+ hdrlen = sizeof(struct buffalo_tag2);
+
+ buflen = hdrlen;
+
+ for (i = 0; i < num_files; i++) {
+ fsize[i] = get_file_size(ifname[i]);
+ if (fsize[i] < 0) {
+ ERR("unable to get size of '%s'", ifname[i]);
+ goto out;
+ }
+ buflen += fsize[i];
+ }
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ offset = hdrlen;
+ for (i = 0; i < num_files; i++) {
+ err = read_file_to_buf(ifname[i], buf + offset, fsize[i]);
+ if (err) {
+ ERR("unable to read from file '%s'", ifname[i]);
+ goto free_buf;
+ }
+
+ offset += fsize[i];
+ }
+
+ if (num_files == 1)
+ fixup_tag(buf, buflen);
+ else
+ fixup_tag2(buf, buflen);
+
+ err = write_buf_to_file(ofname, buf, buflen);
+ if (err) {
+ ERR("unable to write to file '%s'", ofname);
+ goto free_buf;
+ }
+
+ ret = 0;
+
+free_buf:
+ free(buf);
+out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int res = EXIT_FAILURE;
+ int err;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "a:b:c:d:f:hi:l:m:o:p:r:sv:w:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'a':
+ platform = optarg;
+ break;
+ case 'b':
+ brand = optarg;
+ break;
+ case 'c':
+ base1 = strtoul(optarg, NULL, 16);
+ break;
+ case 'd':
+ base2 = strtoul(optarg, NULL, 16);
+ break;
+ case 'f':
+ flag = strtoul(optarg, NULL, 2);
+ break;
+ case 'i':
+ err = process_ifname(optarg);
+ if (err)
+ goto out;
+ break;
+ case 'l':
+ language = optarg;
+ break;
+ case 'm':
+ minor = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'p':
+ product = optarg;
+ break;
+ case 'r':
+ err = process_region(optarg);
+ if (err)
+ goto out;
+ break;
+ case 's':
+ skipcrc = 1;
+ break;
+ case 'v':
+ major = optarg;
+ break;
+ case 'w':
+ hwver = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ err = check_params();
+ if (err)
+ goto out;
+
+ err = tag_file();
+ if (err)
+ goto out;
+
+ res = EXIT_SUCCESS;
+
+out:
+ return res;
+}
diff --git a/tools/firmware-utils/src/buffalo-tftp.c b/tools/firmware-utils/src/buffalo-tftp.c
new file mode 100644
index 0000000..087f995
--- /dev/null
+++ b/tools/firmware-utils/src/buffalo-tftp.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+
+#include "buffalo-lib.h"
+
+#define ERR(fmt, args...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## args ); \
+} while (0)
+
+static char *progname;
+static char *ifname;
+static char *ofname;
+static int do_decrypt;
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -d decrypt instead of encrypt\n"
+" -i <file> read input from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static const unsigned char *crypt_key1 = (unsigned char *)
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+static const unsigned char *crypt_key2 = (unsigned char *)
+ "XYZ0123hijklmnopqABCDEFGHrstuvabcdefgwxyzIJKLMSTUVW456789NOPQR";
+
+static void crypt_header(unsigned char *buf, ssize_t len,
+ const unsigned char *key1, const unsigned char *key2)
+{
+ ssize_t i;
+
+ for (i = 0; i < len; i++) {
+ unsigned int j;
+
+ for (j = 0; key1[j]; j++)
+ if (buf[i] == key1[j]) {
+ buf[i] = key2[j];
+ break;
+ }
+ }
+}
+
+static int crypt_file(void)
+{
+ unsigned char *buf = NULL;
+ ssize_t src_len;
+ int err;
+ int ret = -1;
+
+ src_len = get_file_size(ifname);
+ if (src_len < 0) {
+ ERR("unable to get size of '%s'", ifname);
+ goto out;
+ }
+
+ buf = malloc(src_len);
+ if (buf == NULL) {
+ ERR("no memory for the buffer");
+ goto out;
+ }
+
+ err = read_file_to_buf(ifname, buf, src_len);
+ if (err) {
+ ERR("unable to read from file '%s'", ifname);
+ goto out;
+ }
+
+ if (do_decrypt)
+ crypt_header(buf, 512, crypt_key2, crypt_key1);
+ else
+ crypt_header(buf, 512, crypt_key1, crypt_key2);
+
+ err = write_buf_to_file(ofname, buf, src_len);
+ if (err) {
+ ERR("unable to write to file '%s'", ofname);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ free(buf);
+ return ret;
+}
+
+static int check_params(void)
+{
+ int ret = -1;
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto out;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int res = EXIT_FAILURE;
+ int err;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "di:o:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'd':
+ do_decrypt = 1;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ err = check_params();
+ if (err)
+ goto out;
+
+ err = crypt_file();
+ if (err)
+ goto out;
+
+ res = EXIT_SUCCESS;
+
+out:
+ return res;
+}
diff --git a/tools/firmware-utils/src/csysimg.h b/tools/firmware-utils/src/csysimg.h
new file mode 100644
index 0000000..65ab062
--- /dev/null
+++ b/tools/firmware-utils/src/csysimg.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright (C) 2007,2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program was based on the code found in various Linux
+ * source tarballs released by Edimax for it's devices.
+ * Original author: David Hsu <davidhsu@realtek.com.tw>
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#define SIG_LEN 4
+
+#define ADM_CODE_ADDR 0x80500000
+#define ADM_WEBP_ADDR 0x10000
+#define ADM_WEBP_SIZE 0x10000
+#define ADM_BOOT_SIZE 0x8000
+#define ADM_CONF_SIZE 0x8000
+#define ADM_BOOT_SIG "\x00\x60\x1A\x40"
+
+
+/*
+ * Generic signatures
+ */
+#define SIG_CSYS "CSYS"
+#define SIG_CONF "HS\x00\x00"
+#define SIG_BOOT_RTL "\x00\x00\x40\x21"
+
+/*
+ * Web page signatures
+ */
+#define SIG_BR6104K "WB4K"
+#define SIG_BR6104KP "WBKP"
+#define SIG_BR6104Wg "WBGW"
+#define SIG_BR6104IPC "WBIP"
+#define SIG_BR6114WG SIG_BR6104IPC
+#define SIG_BR6524K "2-K-"
+#define SIG_BR6524KP "2-KP" /* FIXME: valid? */
+#define SIG_BR6524N "WNRA"
+#define SIG_BR6524WG "2-WG" /* FIXME: valid? */
+#define SIG_BR6524WP "2-WP" /* FIXME: valid? */
+#define SIG_BR6541K "4--K"
+#define SIG_BR6541KP "4-KP" /* FIXME: valid? */
+#define SIG_BR6541WP "4-WP" /* FIXME: valid? */
+#define SIG_C54BSR4 SIG_BR6104IPC
+#define SIG_EW7207APg "EWAS"
+#define SIG_PS1205UWg "4000"
+#define SIG_PS3205U "5010"
+#define SIG_PS3205UWg "5011"
+#define SIG_RALINK "RNRA"
+#define SIG_5GXI "5GXI" /* fake signature */
+
+#define SIG_H2BR4 SIG_BR6524K
+#define SIG_H2WR54G SIG_BR6524WG
+
+#define SIG_XRT401D SIG_BR6104K
+#define SIG_XRT402D SIG_BR6524K
+
+/*
+ * CSYS image file header
+ */
+struct csys_header {
+ unsigned char sig[SIG_LEN];
+ uint32_t addr;
+ uint32_t size;
+};
diff --git a/tools/firmware-utils/src/cyg_crc.h b/tools/firmware-utils/src/cyg_crc.h
new file mode 100644
index 0000000..7b59803
--- /dev/null
+++ b/tools/firmware-utils/src/cyg_crc.h
@@ -0,0 +1,109 @@
+//==========================================================================
+//
+// crc.h
+//
+// Interface for the CRC algorithms.
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2002 Andrew Lunn
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Andrew Lunn
+// Contributors: Andrew Lunn
+// Date: 2002-08-06
+// Purpose:
+// Description:
+//
+// This code is part of eCos (tm).
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#ifndef _SERVICES_CRC_CRC_H_
+#define _SERVICES_CRC_CRC_H_
+
+#if 0
+#include <cyg/infra/cyg_type.h>
+#else
+#include <stdint.h>
+typedef uint32_t cyg_uint32;
+typedef uint16_t cyg_uint16;
+#endif
+
+#ifndef __externC
+# ifdef __cplusplus
+# define __externC extern "C"
+# else
+# define __externC extern
+# endif
+#endif
+
+// Compute a CRC, using the POSIX 1003 definition
+
+__externC cyg_uint32
+cyg_posix_crc32(unsigned char *s, int len);
+
+// Gary S. Brown's 32 bit CRC
+
+__externC cyg_uint32
+cyg_crc32(unsigned char *s, int len);
+
+// Gary S. Brown's 32 bit CRC, but accumulate the result from a
+// previous CRC calculation
+
+__externC cyg_uint32
+cyg_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len);
+
+// Ethernet FCS Algorithm
+
+__externC cyg_uint32
+cyg_ether_crc32(unsigned char *s, int len);
+
+// Ethernet FCS algorithm, but accumulate the result from a previous
+// CRC calculation.
+
+__externC cyg_uint32
+cyg_ether_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len);
+
+// 16 bit CRC with polynomial x^16+x^12+x^5+1
+
+__externC cyg_uint16
+cyg_crc16(unsigned char *s, int len);
+
+#endif // _SERVICES_CRC_CRC_H_
+
+
+
diff --git a/tools/firmware-utils/src/cyg_crc16.c b/tools/firmware-utils/src/cyg_crc16.c
new file mode 100644
index 0000000..8b37352
--- /dev/null
+++ b/tools/firmware-utils/src/cyg_crc16.c
@@ -0,0 +1,110 @@
+//==========================================================================
+//
+// crc16.c
+//
+// 16 bit CRC with polynomial x^16+x^12+x^5+1
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): gthomas
+// Contributors: gthomas,asl
+// Date: 2001-01-31
+// Purpose:
+// Description:
+//
+// This code is part of eCos (tm).
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#if 0
+#include <cyg/crc/crc.h>
+#else
+#include "cyg_crc.h"
+#endif
+
+// Table of CRC constants - implements x^16+x^12+x^5+1
+static const cyg_uint16 crc16_tab[] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
+};
+
+cyg_uint16
+cyg_crc16(unsigned char *buf, int len)
+{
+ int i;
+ cyg_uint16 cksum;
+
+ cksum = 0;
+ for (i = 0; i < len; i++) {
+ cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xFF] ^ (cksum << 8);
+ }
+ return cksum;
+}
+
diff --git a/tools/firmware-utils/src/cyg_crc32.c b/tools/firmware-utils/src/cyg_crc32.c
new file mode 100644
index 0000000..9462598
--- /dev/null
+++ b/tools/firmware-utils/src/cyg_crc32.c
@@ -0,0 +1,172 @@
+//==========================================================================
+//
+// crc32.c
+//
+// Gary S. Brown's 32 bit CRC
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): gthomas
+// Contributors: gthomas,asl
+// Date: 2001-01-31
+// Purpose:
+// Description:
+//
+// This code is part of eCos (tm).
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#if 0
+#include <cyg/crc/crc.h>
+#else
+#include "cyg_crc.h"
+#endif
+
+ /* ====================================================================== */
+ /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
+ /* code or tables extracted from it, as desired without restriction. */
+ /* */
+ /* First, the polynomial itself and its table of feedback terms. The */
+ /* polynomial is */
+ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+ /* */
+ /* ====================================================================== */
+
+static const cyg_uint32 crc32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+ };
+
+/* This is the standard Gary S. Brown's 32 bit CRC algorithm, but
+ accumulate the CRC into the result of a previous CRC. */
+cyg_uint32
+cyg_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
+ }
+ return crc32val;
+}
+
+/* This is the standard Gary S. Brown's 32 bit CRC algorithm */
+cyg_uint32
+cyg_crc32(unsigned char *s, int len)
+{
+ return (cyg_crc32_accumulate(0,s,len));
+}
+
+/* Return a 32-bit CRC of the contents of the buffer accumulating the
+ result from a previous CRC calculation. This uses the Ethernet FCS
+ algorithm.*/
+cyg_uint32
+cyg_ether_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len)
+{
+ int i;
+
+ if (s == 0) return 0L;
+
+ crc32val = crc32val ^ 0xffffffff;
+ for (i = 0; i < len; i++) {
+ crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
+ }
+ return crc32val ^ 0xffffffff;
+}
+
+/* Return a 32-bit CRC of the contents of the buffer, using the
+ Ethernet FCS algorithm. */
+cyg_uint32
+cyg_ether_crc32(unsigned char *s, int len)
+{
+ return cyg_ether_crc32_accumulate(0,s,len);
+}
+
+
diff --git a/tools/firmware-utils/src/dgfirmware.c b/tools/firmware-utils/src/dgfirmware.c
new file mode 100644
index 0000000..5ff3b69
--- /dev/null
+++ b/tools/firmware-utils/src/dgfirmware.c
@@ -0,0 +1,376 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define IMG_SIZE 0x3e0000
+
+#define KERNEL_START 0x020000
+#define KERNEL_SIZE 0x0b0000
+
+#define ROOTFS_START 0x0d0000
+#define ROOTFS_SIZE 0x30ffb2
+
+char* app_name;
+
+
+
+
+void print_usage(void)
+{
+ fprintf(stderr, "usage: dgfirmware [<opts>] <img>\n");
+ fprintf(stderr, " <img> firmware image filename\n");
+ fprintf(stderr, " <opts> -h print this message\n");
+ fprintf(stderr, " -f fix the checksum\n");
+ fprintf(stderr, " -x <file> extract the rootfs file to <file>\n");
+ fprintf(stderr, " -xk <file> extract the kernel to <file>\n");
+ fprintf(stderr, " -m <file> merge in rootfs fil\e from <file>\n");
+ fprintf(stderr, " -k <file> merge in kernel from <file>\n");
+ fprintf(stderr, " -w <file> write back the modified firmware\n");
+}
+
+
+unsigned char* read_img(const char *fname)
+{
+ FILE *fp;
+ int size;
+ unsigned char *img;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size != IMG_SIZE) {
+ fprintf(stderr, "%s: image file has wrong size\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ img = malloc(IMG_SIZE);
+ if (img == NULL) {
+ perror(app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
+ fprintf(stderr, "%s: can't read image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+void write_img(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
+ fprintf(stderr, "%s: can't write image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+void write_rootfs(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) {
+ fprintf(stderr, "%s: can't write image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+void write_kernel(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) {
+ fprintf(stderr, "%s: can't write kernel file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+unsigned char* read_rootfs(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+ int size;
+ int i;
+
+ for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++)
+ img[i] = 0xff;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size > ROOTFS_SIZE) {
+ fprintf(stderr, "%s: rootfs image file is too big\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ if (fread(img+ROOTFS_START, 1, size, fp) != size) {
+ fprintf(stderr, "%s: can't read rootfs image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+unsigned char* read_kernel(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+ int size;
+ int i;
+
+ for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++)
+ img[i] = 0xff;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size > KERNEL_SIZE) {
+ fprintf(stderr, "%s: kernel binary file is too big\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ if (fread(img+KERNEL_START, 1, size, fp) != size) {
+ fprintf(stderr, "%s: can't read kernel file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+int get_checksum(unsigned char* img)
+{
+ short unsigned s;
+
+ s = img[0x3dfffc] + (img[0x3dfffd]<<8);
+
+ return s;
+}
+
+
+void set_checksum(unsigned char*img, unsigned short sum)
+{
+ img[0x3dfffc] = sum & 0xff;
+ img[0x3dfffd] = (sum>>8) & 0xff;
+}
+
+
+int compute_checksum(unsigned char* img)
+{
+ int i;
+ short s=0;
+
+ for (i=0; i<0x3dfffc; i++)
+ s += img[i];
+
+ return s;
+}
+
+
+int main(int argc, char* argv[])
+{
+ char *img_fname = NULL;
+ char *rootfs_fname = NULL;
+ char *kernel_fname = NULL;
+ char *new_img_fname = NULL;
+
+ int do_fix_checksum = 0;
+ int do_write = 0;
+ int do_write_rootfs = 0;
+ int do_read_rootfs = 0;
+ int do_write_kernel = 0;
+ int do_read_kernel = 0;
+
+ int i;
+ unsigned char *img;
+ unsigned short img_checksum;
+ unsigned short real_checksum;
+
+ app_name = argv[0];
+
+ for (i=1; i<argc; i++) {
+ if (!strcmp(argv[i], "-h")) {
+ print_usage();
+ return 0;
+ }
+ else if (!strcmp(argv[i], "-f")) {
+ do_fix_checksum = 1;
+ }
+ else if (!strcmp(argv[i], "-x")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write_rootfs = 1;
+ rootfs_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-xk")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write_kernel = 1;
+ kernel_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-m")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_read_rootfs = 1;
+ rootfs_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-k")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_read_kernel = 1;
+ kernel_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-w")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write = 1;
+ new_img_fname = argv[i+1];
+ i++;
+ }
+ else if (img_fname != 0) {
+ fprintf(stderr, "%s: too many arguments\n", app_name);
+ return -1;
+ }
+ else {
+ img_fname = argv[i];
+ }
+ }
+
+ if (img_fname == NULL) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+
+ if ((do_read_rootfs && do_write_rootfs) ||
+ (do_read_kernel && do_write_kernel)) {
+ fprintf(stderr, "%s: conflictuous options\n", app_name);
+ return -1;
+ }
+
+ printf ("** Read firmware file\n");
+ img = read_img(img_fname);
+
+ printf ("Firmware product: %s\n", img+0x3dffbd);
+ printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]);
+
+ if (do_write_rootfs) {
+ printf ("** Write rootfs file\n");
+ write_rootfs(img, rootfs_fname);
+ }
+
+ if (do_write_kernel) {
+ printf ("** Write kernel file\n");
+ write_kernel(img, kernel_fname);
+ }
+
+ if (do_read_rootfs) {
+ printf ("** Read rootfs file\n");
+ read_rootfs(img, rootfs_fname);
+ do_fix_checksum = 1;
+ }
+
+ if (do_read_kernel) {
+ printf ("** Read kernel file\n");
+ read_kernel(img, kernel_fname);
+ do_fix_checksum = 1;
+ }
+
+ img_checksum = get_checksum(img);
+ real_checksum = compute_checksum(img);
+
+ printf ("image checksum = %04x\n", img_checksum);
+ printf ("real checksum = %04x\n", real_checksum);
+
+ if (do_fix_checksum) {
+ if (img_checksum != real_checksum) {
+ printf ("** Bad Checksum, fix it\n");
+ set_checksum(img, real_checksum);
+ }
+ else {
+ printf ("** Checksum is correct, good\n");
+ }
+ }
+
+ if (do_write) {
+ printf ("** Write image file\n");
+ write_img(img, new_img_fname);
+ }
+
+ free(img);
+ return 0;
+}
+
diff --git a/tools/firmware-utils/src/dgn3500sum.c b/tools/firmware-utils/src/dgn3500sum.c
new file mode 100644
index 0000000..00a0c5f
--- /dev/null
+++ b/tools/firmware-utils/src/dgn3500sum.c
@@ -0,0 +1,167 @@
+/* **************************************************************************
+
+ This program creates a modified 16bit checksum used for the Netgear
+ DGN3500 series routers. The difference between this and a standard
+ checksum is that every 0x100 bytes added 0x100 have to be subtracted
+ from the sum.
+
+ (C) 2013 Marco Antonio Mauro <marcus90 at gmail.com>
+
+ Based on previous unattributed work.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ ************************************************************************* */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+unsigned char PidDataWW[70] =
+{
+ 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
+ 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x37,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
+} ;
+
+unsigned char PidDataDE[70] =
+{
+ 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x37,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
+} ;
+
+unsigned char PidDataNA[70] =
+{
+ 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
+ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x37,
+ 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+ 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
+} ;
+
+/* *******************************************************************
+ Reads the file into memory and returns pointer to the buffer. */
+static char *readfile(char *filename, int *size)
+{
+ FILE *fp;
+ char *buffer;
+ struct stat info;
+
+ if (stat(filename,&info)!=0)
+ return NULL;
+
+ if ((fp=fopen(filename,"r"))==NULL)
+ return NULL;
+
+ buffer=NULL;
+ for (;;)
+ {
+ if ((buffer=(char *)malloc(info.st_size+1))==NULL)
+ break;
+
+ if (fread(buffer,1,info.st_size,fp)!=info.st_size)
+ {
+ free(buffer);
+ buffer=NULL;
+ break;
+ }
+
+ buffer[info.st_size]='\0';
+ if(size) *size = info.st_size;
+
+ break;
+ }
+
+ (void)fclose(fp);
+
+ return buffer;
+}
+
+
+/* ******************************************************************* */
+int main(int argc, char** argv)
+{
+ unsigned long start, i;
+ char *endptr, *buffer, *p;
+ int count; // size of file in bytes
+ unsigned short sum, sum1;
+ char sumbuf[9];
+
+ if(argc < 3) {
+ printf("ERROR: Argument missing!\n\nUsage %s filename starting offset in hex [PID code]\n\n", argv[0]);
+ return 1;
+ }
+
+
+ FILE *fp = fopen(argv[1], "a");
+ if(!fp) {
+ printf("ERROR: File not writeable!\n");
+ return 1;
+ }
+ if(argc = 4)
+ {
+ printf("%s: PID type: %s\n", argv[0], argv[3]);
+ if(strcmp(argv[3], "DE")==0)
+ fwrite(PidDataDE, sizeof(PidDataDE), sizeof(char), fp); /* write DE pid */
+ else if(strcmp(argv[3], "NA")==0)
+ fwrite(PidDataNA, sizeof(PidDataNA), sizeof(char), fp); /* write NA pid */
+ else /* if(strcmp(argv[3], "WW")) */
+ fwrite(PidDataWW, sizeof(PidDataWW), sizeof(char), fp); /* write WW pid */
+ }
+ else
+ fwrite(PidDataWW, sizeof(PidDataWW), sizeof(char), fp); /* write WW pid if unspecified */
+
+ fclose(fp);
+
+ /* Read the file to calculate the checksums */
+ buffer = readfile(argv[1], &count);
+ if(!buffer) {
+ printf("ERROR: File %s not found!\n", argv[1]);
+ return 1;
+ }
+
+ p = buffer;
+ for(i = 0; i < count; i++)
+ {
+ sum += p[i];
+ }
+
+ start = strtol(argv[2], &endptr, 16);
+ p = buffer+start;
+ sum1 = 0;
+ for(i = 0; i < count - start; i++)
+ {
+ sum1 += p[i];
+ }
+
+ sprintf(sumbuf,"%04X%04X",sum1,sum);
+ /* Append the 2 checksums to end of file */
+ fp = fopen(argv[1], "a");
+ if(!fp) {
+ printf("ERROR: File not writeable!\n");
+ return 1;
+ }
+ fwrite(sumbuf, 8, sizeof(char), fp);
+ fclose(fp);
+ free(buffer);
+ return 0;
+}
diff --git a/tools/firmware-utils/src/edimax_fw_header.c b/tools/firmware-utils/src/edimax_fw_header.c
new file mode 100644
index 0000000..b85e3a1
--- /dev/null
+++ b/tools/firmware-utils/src/edimax_fw_header.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2014 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#define MAX_MAGIC_LEN 16
+#define MAX_MODEL_LEN 32
+#define MAX_VERSION_LEN 14
+#define MAX_MTD_NAME_LEN 16
+
+#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+struct edimax_header {
+ char magic[MAX_MAGIC_LEN];
+ char model[MAX_MODEL_LEN];
+ unsigned char force;
+ unsigned char header_csum;
+ unsigned char data_csum;
+ uint32_t data_size;
+ uint32_t start_addr;
+ uint32_t end_addr;
+ char fw_version[MAX_VERSION_LEN];
+ unsigned char type;
+ char mtd_name[MAX_MTD_NAME_LEN];
+} __attribute__ ((packed));
+
+/*
+ * Globals
+ */
+static char *ofname;
+static char *ifname;
+static char *progname;
+
+static char *model;
+static char *magic = "eDiMaX";
+static char *fw_version = "";
+static char *mtd_name;
+static int force;
+static uint32_t start_addr;
+static uint32_t end_addr;
+static uint8_t image_type;
+static int data_size;
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -e <addr> set end addr to <addr>\n"
+" -f set force flag\n"
+" -h show this screen\n"
+" -i <file> read input data from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -m <model> set model to <model>\n"
+" -M <magic> set image magic to <magic>\n"
+" -n <name> set MTD device name to <name>\n"
+" -s <addr> set start address to <addr>\n"
+" -t <type> set image type to <type>\n"
+" -v <version> set firmware version to <version>\n"
+ );
+
+ exit(status);
+}
+
+int
+str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+int
+str2u8(char *arg, uint8_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) {
+ return -1;
+ }
+
+ *val = t & 0xFF;
+ return 0;
+}
+
+static int get_file_size(char *name)
+{
+ struct stat st;
+ int res;
+
+ res = stat(name, &st);
+ if (res){
+ ERRS("stat failed on %s", name);
+ return -1;
+ }
+
+ return st.st_size;
+}
+
+static int read_to_buf(char *name, char *buf, int buflen)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(name, "r");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, buflen, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+out_close:
+ fclose(f);
+out:
+ return ret;
+}
+
+static int check_options(void)
+{
+#define CHKSTR(_name, _msg) \
+ do { \
+ if (_name == NULL) { \
+ ERR("no %s specified", _msg); \
+ return -1; \
+ } \
+ } while (0)
+
+#define CHKSTRLEN(_name, _msg) \
+ do { \
+ int field_len; \
+ CHKSTR(_name, _msg); \
+ field_len = FIELD_SIZEOF(struct edimax_header, _name) - 1; \
+ if (strlen(_name) > field_len) { \
+ ERR("'%s' is too long, max %s length is %d", \
+ _name, _msg, field_len); \
+ return -1; \
+ } \
+ } while (0)
+
+ CHKSTR(ofname, "output file");
+ CHKSTR(ifname, "input file");
+
+ CHKSTRLEN(magic, "magic");
+ CHKSTRLEN(model, "model");
+ CHKSTRLEN(mtd_name, "MTD device name");
+ CHKSTRLEN(fw_version, "firware version");
+
+ data_size = get_file_size(ifname);
+ if (data_size < 0)
+ return -1;
+
+ return 0;
+}
+
+static int write_fw(char *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "w");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ DBG("firmware file \"%s\" completed", ofname);
+
+ ret = EXIT_SUCCESS;
+
+out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+out:
+ return ret;
+}
+
+static unsigned char checksum(unsigned char *p, unsigned len)
+{
+ unsigned char csum = 0;
+
+ while (len--)
+ csum += *p++;
+
+ csum ^= 0xb9;
+
+ return csum;
+}
+
+static int build_fw(void)
+{
+ int buflen;
+ char *buf;
+ char *data;
+ struct edimax_header *hdr;
+ int ret = EXIT_FAILURE;
+
+ buflen = sizeof(struct edimax_header) + data_size;
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ data = buf + sizeof(struct edimax_header);
+
+ /* read input file */
+ ret = read_to_buf(ifname, data, data_size);
+ if (ret)
+ goto out_free_buf;
+
+ /* fill firmware header */
+ hdr = (struct edimax_header *)buf;
+ memset(hdr, 0, sizeof(struct edimax_header));
+
+ strncpy(hdr->model, model, sizeof(hdr->model));
+ strncpy(hdr->magic, magic, sizeof(hdr->magic));
+ strncpy(hdr->fw_version, fw_version, sizeof(hdr->fw_version));
+ strncpy(hdr->mtd_name, mtd_name, sizeof(hdr->mtd_name));
+
+ hdr->force = force;
+ hdr->start_addr = htonl(start_addr);
+ hdr->end_addr = htonl(end_addr);
+ hdr->data_size = htonl(data_size);
+ hdr->type = image_type;
+
+ hdr->data_csum = checksum((unsigned char *)data, data_size);
+ hdr->header_csum = checksum((unsigned char *)hdr,
+ sizeof(struct edimax_header));
+
+ ret = write_fw(buf, buflen);
+ if (ret)
+ goto out_free_buf;
+
+ ret = EXIT_SUCCESS;
+
+out_free_buf:
+ free(buf);
+out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+
+ progname = basename(argv[0]);
+
+ while (1) {
+ int c;
+
+ c = getopt(argc, argv, "e:fhi:o:m:M:n:s:t:v:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'e':
+ if (str2u32(optarg, &end_addr)) {
+ ERR("%s is invalid '%s'",
+ "end address", optarg);
+ goto out;
+ }
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'm':
+ model = optarg;
+ break;
+ case 'M':
+ magic = optarg;
+ break;
+ case 'n':
+ mtd_name = optarg;
+ break;
+ case 's':
+ if (str2u32(optarg, &start_addr)) {
+ ERR("%s is invalid '%s'",
+ "start address", optarg);
+ goto out;
+ }
+ break;
+ case 't':
+ if (str2u8(optarg, &image_type)) {
+ ERR("%s is invalid '%s'",
+ "image type", optarg);
+ goto out;
+ }
+ break;
+ case 'v':
+ fw_version = optarg;
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret)
+ goto out;
+
+ ret = build_fw();
+
+out:
+ return ret;
+}
diff --git a/tools/firmware-utils/src/encode_crc.c b/tools/firmware-utils/src/encode_crc.c
new file mode 100644
index 0000000..647fb92
--- /dev/null
+++ b/tools/firmware-utils/src/encode_crc.c
@@ -0,0 +1,151 @@
+/* **************************************************************************
+
+ This program creates a CRC checksum and encodes the file that is named
+ in the command line.
+
+ Compile with: gcc encode_crc.c -Wall -o encode_crc
+
+ Author: Michael Margraf (michael.margraf@freecom.com)
+ Copyright: Freecom Technology GmbH, Berlin, 2004
+ www.freecom.com
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ ************************************************************************* */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+// *******************************************************************
+// CCITT polynom G(x)=x^16+x^12+x^5+1
+#define POLYNOM 0x1021
+
+// CRC algorithm with MSB first
+int make_crc16(int crc, char new)
+{
+ int i;
+ crc = crc ^ (((int)new) << 8);
+
+ for(i=0; i<8; i++) { // work on 8 bits in "new"
+ crc <<= 1; // MSBs first
+ if(crc & 0x10000) crc ^= POLYNOM;
+ }
+ return crc & 0xFFFF;
+}
+
+// *******************************************************************
+// Reads the file "filename" into memory and returns pointer to the buffer.
+static char *readfile(char *filename, int *size)
+{
+ FILE *fp;
+ char *buffer;
+ struct stat info;
+
+ if (stat(filename,&info)!=0)
+ return NULL;
+
+ if ((fp=fopen(filename,"r"))==NULL)
+ return NULL;
+
+ buffer=NULL;
+ for (;;)
+ {
+ if ((buffer=(char *)malloc(info.st_size+1))==NULL)
+ break;
+
+ if (fread(buffer,1,info.st_size,fp)!=info.st_size)
+ {
+ free(buffer);
+ buffer=NULL;
+ break;
+ }
+
+ buffer[info.st_size]='\0';
+ if(size) *size = info.st_size;
+
+ break;
+ }
+
+ (void)fclose(fp);
+
+ return buffer;
+}
+
+
+// *******************************************************************
+int main(int argc, char** argv)
+{
+ if(argc < 3) {
+ printf("ERROR: Argument missing!\n\n");
+ return 1;
+ }
+
+ int count; // size of file in bytes
+ char *p, *master = readfile(argv[1], &count);
+ if(!master) {
+ printf("ERROR: File not found!\n");
+ return 1;
+ }
+
+ int crc = 0xFFFF, z;
+
+ p = master;
+ for(z=0; z<count; z++)
+ crc = make_crc16(crc, *(p++)); // calculate CRC
+ short crc16 = (short)crc;
+
+ /*
+ if(argc > 2) { // with flag for device recognition ?
+ p = argv[2];
+ for(z=strlen(p); z>0; z--) {
+ crc ^= (int)(*p);
+ *(p++) = (char)crc; // encode device flag
+ }
+ }
+ */
+
+ p = master;
+ for(z=0; z<count; z++) {
+ crc ^= (int)(*p);
+ *(p++) = (char)crc; // encode file
+ }
+
+
+ // write encoded file...
+ FILE *fp = fopen(argv[2], "w");
+ if(!fp) {
+ printf("ERROR: File not writeable!\n");
+ return 1;
+ }
+
+ if(argc > 3) { // add flag for device recognition ?
+ fwrite(argv[3], strlen(argv[3]), sizeof(char), fp);
+ }
+ else {
+ // Device is an FSG, so byte swap (IXP4xx is big endian)
+ crc16 = ((crc16 >> 8) & 0xFF) | ((crc16 << 8) & 0xFF00);
+ }
+
+ fwrite(&crc16, 1, sizeof(short), fp); // first write CRC
+
+ fwrite(master, count, sizeof(char), fp); // write content
+ fclose(fp);
+
+ free(master);
+ return 0;
+}
diff --git a/tools/firmware-utils/src/fix-u-media-header.c b/tools/firmware-utils/src/fix-u-media-header.c
new file mode 100644
index 0000000..21f184e
--- /dev/null
+++ b/tools/firmware-utils/src/fix-u-media-header.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "cyg_crc.h"
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#define IH_MAGIC 0x27051956 /* Image Magic Number */
+#define IH_NMLEN 32 /* Image Name Length */
+
+#define UM_MAGIC 0x55525F46
+#define UM_HEADER_LEN 12
+
+/*
+ * all data in network byte order (aka natural aka bigendian)
+ */
+struct u_media_header {
+ uint32_t ih_magic; /* Image Header Magic Number */
+ uint32_t ih_hcrc; /* Image Header CRC Checksum */
+ uint32_t ih_time; /* Image Creation Timestamp */
+ uint32_t ih_size; /* Image Data Size */
+ uint32_t ih_load; /* Data Load Address */
+ uint32_t ih_ep; /* Entry Point Address */
+ uint32_t ih_dcrc; /* Image Data CRC Checksum */
+ uint8_t ih_os; /* Operating System */
+ uint8_t ih_arch; /* CPU architecture */
+ uint8_t ih_type; /* Image Type */
+ uint8_t ih_comp; /* Compression Type */
+ uint8_t ih_name[IH_NMLEN - UM_HEADER_LEN]; /* Image Name */
+
+ uint32_t ih_UMedia_magic; /* U-Media magic number */
+ uint32_t ih_UMedia_boardID; /* U-Media board ID */
+ uint8_t ih_UMedia_imageType; /* U-Media image type */
+ uint8_t ih_UMedia_LoadDefault; /* U-Media load to factory default setting */
+ uint8_t ih_UMedia_temp1; /* U-Media didn't use this tag */
+ uint8_t ih_UMedia_temp2; /* U-Media didn't use this tag */
+} __attribute__ ((packed));
+
+struct if_info {
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+};
+
+static char *progname;
+static char *ofname;
+static struct if_info if_info;
+static int factory_defaults;
+static uint32_t board_id;
+static uint8_t image_type;
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board_id> set board ID to <board_id>\n"
+" -i <file> read input from the file <file>\n"
+" -F load factory defaults\n"
+" -o <file> write output to the file <file>\n"
+" -T <type> set image type to <type>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static int str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+static int str2u8(char *arg, uint8_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ if (t > 255)
+ return -1;
+
+ *val = t;
+ return 0;
+}
+
+static int get_file_stat(struct if_info *fdata)
+{
+ struct stat st;
+ int res;
+
+ if (fdata->file_name == NULL)
+ return 0;
+
+ res = stat(fdata->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", fdata->file_name);
+ return res;
+ }
+
+ fdata->file_size = st.st_size;
+ return 0;
+}
+
+static int read_to_buf(struct if_info *fdata, char *buf)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(fdata->file_name, "r");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", fdata->file_name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, fdata->file_size, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", fdata->file_name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+out_close:
+ fclose(f);
+out:
+ return ret;
+}
+
+static int check_options(void)
+{
+ int ret;
+
+ if (ofname == NULL) {
+ ERR("no %s specified", "output file");
+ return -1;
+ }
+
+ if (if_info.file_name == NULL) {
+ ERR("no %s specified", "input file");
+ return -1;
+ }
+
+ ret = get_file_stat(&if_info);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int write_fw(char *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "w");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ ret = EXIT_SUCCESS;
+
+out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+out:
+ return ret;
+}
+
+static int fix_header(void)
+{
+ int buflen;
+ char *buf;
+ uint32_t crc, crc_orig;
+ struct u_media_header *hdr;
+ int ret = EXIT_FAILURE;
+
+ buflen = if_info.file_size;
+ if (buflen < sizeof(*hdr)) {
+ ERR("invalid input file\n");
+ return ret;
+ }
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ ret = read_to_buf(&if_info, buf);
+ if (ret)
+ goto out_free_buf;
+
+ hdr = (struct u_media_header *) buf;
+ if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+ ERR("invalid input file, bad magic\n");
+ goto out_free_buf;
+ }
+
+ /* verify header CRC */
+ crc_orig = ntohl(hdr->ih_hcrc);
+ hdr->ih_hcrc = 0;
+ crc = cyg_ether_crc32((unsigned char *)hdr, sizeof(*hdr));
+ if (crc != crc_orig) {
+ ERR("invalid input file, bad header CRC\n");
+ goto out_free_buf;
+ }
+
+ hdr->ih_name[IH_NMLEN - UM_HEADER_LEN - 1] = '\0';
+
+ /* set U-Media specific fields */
+ hdr->ih_UMedia_magic = htonl(UM_MAGIC);
+ hdr->ih_UMedia_boardID = htonl(board_id);
+ hdr->ih_UMedia_imageType = image_type;
+ hdr->ih_UMedia_LoadDefault = (factory_defaults) ? 1 : 0;
+
+ /* update header CRC */
+ crc = cyg_ether_crc32((unsigned char *)hdr, sizeof(*hdr));
+ hdr->ih_hcrc = htonl(crc);
+
+ ret = write_fw(buf, buflen);
+ if (ret)
+ goto out_free_buf;
+
+ DBG("U-Media header fixed in \"%s\"", ofname);
+
+ ret = EXIT_SUCCESS;
+
+out_free_buf:
+ free(buf);
+out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+
+ progname = basename(argv[0]);
+
+ while (1) {
+ int c;
+
+ c = getopt(argc, argv, "B:Fi:o:T:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'B':
+ if (str2u32(optarg, &board_id)) {
+ ERR("%s is invalid '%s'",
+ "board ID", optarg);
+ goto out;
+ }
+ break;
+ case 'T':
+ if (str2u8(optarg, &image_type)) {
+ ERR("%s is invalid '%s'",
+ "image type", optarg);
+ goto out;
+ }
+ break;
+ case 'F':
+ factory_defaults = 1;
+ break;
+ case 'i':
+ if_info.file_name = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret)
+ goto out;
+
+ ret = fix_header();
+
+out:
+ return ret;
+}
diff --git a/tools/firmware-utils/src/fw.h b/tools/firmware-utils/src/fw.h
new file mode 100644
index 0000000..e37859c
--- /dev/null
+++ b/tools/firmware-utils/src/fw.h
@@ -0,0 +1,70 @@
+/*
+ * * Copyright (C) 2007 Ubiquiti Networks, Inc.
+ * *
+ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * */
+
+#ifndef FW_INCLUDED
+#define FW_INCLUDED
+
+#include <sys/types.h>
+
+#define MAGIC_HEADER "OPEN"
+#define MAGIC_PART "PART"
+#define MAGIC_END "END."
+
+#define MAGIC_LENGTH 4
+
+typedef struct header {
+ char magic[MAGIC_LENGTH];
+ char version[256];
+ u_int32_t crc;
+ u_int32_t pad;
+} __attribute__ ((packed)) header_t;
+
+typedef struct part {
+ char magic[MAGIC_LENGTH];
+ char name[16];
+ char pad[12];
+ u_int32_t memaddr;
+ u_int32_t index;
+ u_int32_t baseaddr;
+ u_int32_t entryaddr;
+ u_int32_t data_size;
+ u_int32_t part_size;
+} __attribute__ ((packed)) part_t;
+
+typedef struct part_crc {
+ u_int32_t crc;
+ u_int32_t pad;
+} __attribute__ ((packed)) part_crc_t;
+
+typedef struct signature {
+ char magic[MAGIC_LENGTH];
+ u_int32_t crc;
+ u_int32_t pad;
+} __attribute__ ((packed)) signature_t;
+
+#define VERSION "1.2"
+
+#define INFO(...) fprintf(stdout, __VA_ARGS__)
+#define ERROR(...) fprintf(stderr, "ERROR: "__VA_ARGS__)
+#define WARN(...) fprintf(stderr, "WARN: "__VA_ARGS__)
+#define DEBUG(...) do {\
+ if (debug) \
+ fprintf(stdout, "DEBUG: "__VA_ARGS__); \
+} while (0);
+
+#endif
diff --git a/tools/firmware-utils/src/hcsmakeimage.c b/tools/firmware-utils/src/hcsmakeimage.c
new file mode 100644
index 0000000..603ea88
--- /dev/null
+++ b/tools/firmware-utils/src/hcsmakeimage.c
@@ -0,0 +1,181 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include "bcmalgo.h"
+
+
+int flag_print_version;
+int flag_print_help;
+int flag_compress;
+
+uint16_t sa2100_magic = 0x2100;
+uint16_t sa3349_magic = 0x3349;
+uint32_t default_date = 0x00000000; //A long time ago in a galaxy far far away....
+uint32_t default_load_address = 0x80010000; //The default load_address for the firmware image
+
+static void print_help ( const char* ename )
+{
+ printf ( "Firmware image packer and calculator for broadcom-based modems.\n" );
+ printf ( "Part of bcm-utils package.\n" );
+ printf ( "(c) 2009 Necromant (http://necromant.ath.cx). Thanks to Luke-jr for his initial work.\n" );
+ printf ( "usage: %s [options]\n", ename );
+ printf ( "Valid options are:\n" );
+ printf ( "--magic_bytes=value \t- specify magic bytes at the beginning of the image. default - 3349\n" );
+ printf ( "\t\t\t these can be sa2100 (for DPC2100 modem),\n\t\t\t sa3349 (haxorware guys use this one for some reason),\n\t\t\t or a custom hex value e.g. 0xFFFF\n" );
+ printf ( "--compress \t\t - Make use of LZMA (weird!) compression (Doesn't work yet).\n" );
+ printf ( "--rev_maj=value\t\t - major revision number. default 0\n" );
+ printf ( "--rev_min=value\t\t - minor revision number default 0\n" );
+ printf ( "--filename=value\t - use this filename in header instead of default (input filename)\n" );
+ printf ( "--ldaddress=value\t - hex value of the target load address. defaults to 0x80010000\n" );
+ printf ( "--input_file=value\t - What file are we packing?\n" );
+ printf ( "--output_file=value\t - What file shall we write? (default: image.bin)\n" );
+#ifdef _HAX0RSTYLE
+ printf ( "--credz\t - Give some credz!\n" );
+#endif
+ printf ( "\n" );
+}
+
+
+int main ( int argc, char** argv )
+{
+ if ( argc<2 )
+ {
+ print_help ( argv[0] );
+ }
+
+ static struct option long_options[] =
+ {
+ {"magic_bytes", required_argument, 0, 'm'},
+ {"rev_maj", required_argument, 0, 'j'},
+ {"rev_min", required_argument, 0, 'n'},
+ {"ldaddress", required_argument, 0, 'l'},
+ {"filename", required_argument, 0, 'f'},
+ {"input_file", required_argument, 0, 'i'},
+ {"output_file", required_argument, 0, 'o'},
+ {"compress", no_argument, &flag_compress, 'c'},
+ {"version", no_argument, &flag_print_version, 'v'},
+ {"help", no_argument, &flag_print_help, 'h'},
+ {0, 0, 0, 0}
+ };
+ int option_index = 0;
+ int opt_result=0;
+ char* filename=NULL;
+ char* input=NULL;
+ char* magic=NULL;
+ char* major=NULL;
+ char* minor=NULL;
+ char* ldaddr=NULL;
+ char* output=NULL;
+
+ while ( opt_result>=0 )
+ {
+ opt_result = getopt_long ( argc, argv, "m:j:n:f:i:o:vh", long_options, &option_index );
+ switch ( opt_result )
+ {
+ case 0:
+ printf ( "o!\n" );
+ break;
+ case 'h':
+ print_help ( argv[0] );
+ break;
+ case 'l':
+ ldaddr=optarg;
+ break;
+ case 'f':
+ filename=optarg;
+ break;
+ case 'i':
+ input=optarg;
+ break;
+ case 'o':
+ output=optarg;
+ break;
+ case 'm':
+ magic=optarg;
+ break;
+ case 'j':
+ major=optarg;
+ break;
+ case 'n':
+ minor=optarg;
+ break;
+ }
+ }
+ if ( input==NULL )
+ {
+ printf ( "Telepaths are still on holidays. I guess you should tell me what file should I process.\n\n" );
+ exit ( 1 );
+ }
+ if ( access ( input,R_OK ) !=0 )
+ {
+ printf ( "I cannot access the file %s. Is it there? Am I allowed?\n\n", input );
+ exit ( 1 );
+ }
+ uint32_t magicnum=sa2100_magic;
+
+ if ( magic )
+ {
+ if ( strcmp ( magic,"sa2100" ) ==0 ) magicnum=sa2100_magic; else
+ if ( strcmp ( magic,"sa3349" ) ==0 ) magicnum=sa3349_magic; else
+ {
+ sscanf ( magic, "0x%04X", &magicnum );
+ }
+ }
+ unsigned int majrev=0;
+ if ( major )
+ {
+ sscanf ( major, "%d", &majrev );
+ }
+ unsigned int minrev=0;
+ if ( minor )
+ {
+ sscanf ( minor, "%d", &minrev );
+ }
+ uint32_t ldaddress = default_load_address;
+ if ( ldaddr )
+ {
+ sscanf ( ldaddr, "0x%08X", &ldaddress );
+ }
+ char* dupe = strdup(input);
+ char* fname = basename ( dupe );
+ if ( filename )
+ {
+ fname = filename;
+ }
+ struct timeval tm;
+ gettimeofday ( &tm,NULL );
+ struct stat buf;
+ stat ( input,&buf );
+ ldr_header_t* head = construct_header ( magicnum, (uint16_t) majrev, (uint16_t) minrev, ( uint32_t ) tm.tv_sec, ( uint32_t ) buf.st_size, ldaddress, fname, get_file_crc ( input ) );
+ free(dupe);
+ //uint32_t magic, uint16_t rev_maj,uint16_t rev_min, uint32_t build_date, uint32_t filelen, uint32_t ldaddress, const char* filename, uint32_t crc
+ //FILE* fd = fopen ("/tftpboot/haxorware11rev32.bin","r");
+ //fread(head,sizeof(ldr_header_t),1,fd);
+ char* filebuffer = malloc ( buf.st_size+10 );
+ FILE* fd = fopen ( input,"r" );
+ fread ( filebuffer, 1, buf.st_size,fd );
+ if (!output)
+ {
+ output = malloc(strlen(input+5));
+ strcpy(output,input);
+ strcat(output,".bin");
+ }
+ dump_header ( head );
+ FILE* fd_out = fopen ( output,"w+" );
+ if (!fd_out)
+ {
+ fprintf(stderr, "Failed to open output file: %s\n", output);
+ exit(1);
+ }
+ fwrite ( head,1,sizeof ( ldr_header_t ),fd_out );
+ fwrite ( filebuffer,1,buf.st_size,fd_out );
+ printf("Firmware image %s is ready\n", output);
+ return 0;
+}
diff --git a/tools/firmware-utils/src/imagetag.c b/tools/firmware-utils/src/imagetag.c
new file mode 100644
index 0000000..90fb7a4
--- /dev/null
+++ b/tools/firmware-utils/src/imagetag.c
@@ -0,0 +1,492 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Axel Gembe <ago@bastart.eu.org>
+ * Copyright (C) 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#include "bcm_tag.h"
+#include "imagetag_cmdline.h"
+#include "cyg_crc.h"
+
+#define DEADCODE 0xDEADC0DE
+
+/* Kernel header */
+struct kernelhdr {
+ uint32_t loadaddr; /* Kernel load address */
+ uint32_t entry; /* Kernel entry point address */
+ uint32_t lzmalen; /* Compressed length of the LZMA data that follows */
+};
+
+static char pirellitab[NUM_PIRELLI][BOARDID_LEN] = PIRELLI_BOARDS;
+
+void int2tag(char *tag, uint32_t value) {
+ uint32_t network = htonl(value);
+ memcpy(tag, (char *)(&network), 4);
+}
+
+uint32_t compute_crc32(uint32_t crc, FILE *binfile, size_t compute_start, size_t compute_len)
+{
+ uint8_t readbuf[1024];
+ size_t read;
+
+ fseek(binfile, compute_start, SEEK_SET);
+
+ /* read block of 1024 bytes */
+ while (binfile && !feof(binfile) && !ferror(binfile) && (compute_len >= sizeof(readbuf))) {
+ read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), binfile);
+ crc = cyg_crc32_accumulate(crc, readbuf, read);
+ compute_len = compute_len - read;
+ }
+
+ /* Less than 1024 bytes remains, read compute_len bytes */
+ if (binfile && !feof(binfile) && !ferror(binfile) && (compute_len > 0)) {
+ read = fread(readbuf, sizeof(uint8_t), compute_len, binfile);
+ crc = cyg_crc32_accumulate(crc, readbuf, read);
+ }
+
+ return crc;
+}
+
+size_t getlen(FILE *fp)
+{
+ size_t retval, curpos;
+
+ if (!fp)
+ return 0;
+
+ curpos = ftell(fp);
+ fseek(fp, 0, SEEK_END);
+ retval = ftell(fp);
+ fseek(fp, curpos, SEEK_SET);
+
+ return retval;
+}
+
+int tagfile(const char *kernel, const char *rootfs, const char *bin, \
+ const struct gengetopt_args_info *args, \
+ uint32_t flash_start, uint32_t image_offset, \
+ uint32_t block_size, uint32_t load_address, uint32_t entry)
+{
+ struct bcm_tag tag;
+ struct kernelhdr khdr;
+ FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile = NULL, *cfefile = NULL;
+ size_t cfeoff, cfelen, kerneloff, kernellen, rootfsoff, rootfslen, \
+ read, imagelen, rootfsoffpadlen = 0, kernelfslen, kerneloffpadlen = 0, oldrootfslen, \
+ rootfsend;
+ uint8_t readbuf[1024];
+ uint32_t imagecrc = IMAGETAG_CRC_START;
+ uint32_t kernelcrc = IMAGETAG_CRC_START;
+ uint32_t rootfscrc = IMAGETAG_CRC_START;
+ uint32_t kernelfscrc = IMAGETAG_CRC_START;
+ uint32_t fwaddr = 0;
+ uint8_t crc_val;
+ const uint32_t deadcode = htonl(DEADCODE);
+ int i;
+ int is_pirelli = 0;
+
+
+ memset(&tag, 0, sizeof(struct bcm_tag));
+
+ if (!kernel || !rootfs) {
+ fprintf(stderr, "imagetag can't create an image without both kernel and rootfs\n");
+ }
+
+ if (kernel && !(kernelfile = fopen(kernel, "rb"))) {
+ fprintf(stderr, "Unable to open kernel \"%s\"\n", kernel);
+ return 1;
+ }
+
+ if (rootfs && !(rootfsfile = fopen(rootfs, "rb"))) {
+ fprintf(stderr, "Unable to open rootfs \"%s\"\n", rootfs);
+ return 1;
+ }
+
+ if (!bin || !(binfile = fopen(bin, "wb+"))) {
+ fprintf(stderr, "Unable to open output file \"%s\"\n", bin);
+ return 1;
+ }
+
+ if ((args->cfe_given) && (args->cfe_arg)) {
+ if (!(cfefile = fopen(args->cfe_arg, "rb"))) {
+ fprintf(stderr, "Unable to open CFE file \"%s\"\n", args->cfe_arg);
+ }
+ }
+
+ fwaddr = flash_start + image_offset;
+ if (cfefile) {
+ cfeoff = flash_start;
+ cfelen = getlen(cfefile);
+ /* Seek to the start of the file after tag */
+ fseek(binfile, sizeof(tag), SEEK_SET);
+
+ /* Write the cfe */
+ while (cfefile && !feof(cfefile) && !ferror(cfefile)) {
+ read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), cfefile);
+ fwrite(readbuf, sizeof(uint8_t), read, binfile);
+ }
+
+ } else {
+ cfeoff = 0;
+ cfelen = 0;
+ }
+
+ if (!args->root_first_flag) {
+ /* Build the kernel address and length (doesn't need to be aligned, read only) */
+ kerneloff = fwaddr + sizeof(tag);
+
+ kernellen = getlen(kernelfile);
+
+ if (!args->kernel_file_has_header_flag) {
+ /* Build the kernel header */
+ khdr.loadaddr = htonl(load_address);
+ khdr.entry = htonl(entry);
+ khdr.lzmalen = htonl(kernellen);
+
+ /* Increase the kernel size by the header size */
+ kernellen += sizeof(khdr);
+ }
+
+ /* Build the rootfs address and length */
+ rootfsoff = kerneloff + kernellen;
+ /* align the start if requested */
+ if (args->align_rootfs_flag)
+ rootfsoff = (rootfsoff % block_size) > 0 ? (((rootfsoff / block_size) + 1) * block_size) : rootfsoff;
+ else
+ rootfsoff = (rootfsoff % 4) > 0 ? (((rootfsoff / 4) + 1) * 4) : rootfsoff;
+
+ /* align the end */
+ rootfsend = rootfsoff + getlen(rootfsfile);
+ if ((rootfsend % block_size) > 0)
+ rootfsend = (((rootfsend / block_size) + 1) * block_size);
+ rootfslen = rootfsend - rootfsoff;
+ imagelen = rootfsoff + rootfslen - kerneloff + sizeof(deadcode);
+ rootfsoffpadlen = rootfsoff - (kerneloff + kernellen);
+
+ /* Seek to the start of the kernel */
+ fseek(binfile, kerneloff - fwaddr + cfelen, SEEK_SET);
+
+ /* Write the kernel header */
+ fwrite(&khdr, sizeof(khdr), 1, binfile);
+
+ /* Write the kernel */
+ while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) {
+ read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), kernelfile);
+ fwrite(readbuf, sizeof(uint8_t), read, binfile);
+ }
+
+ /* Write the RootFS */
+ fseek(binfile, rootfsoff - fwaddr + cfelen, SEEK_SET);
+ while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) {
+ read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), rootfsfile);
+ fwrite(readbuf, sizeof(uint8_t), read, binfile);
+ }
+
+ /* Align image to specified erase block size and append deadc0de */
+ printf("Data alignment to %dk with 'deadc0de' appended\n", block_size/1024);
+ fseek(binfile, rootfsoff + rootfslen - fwaddr + cfelen, SEEK_SET);
+ fwrite(&deadcode, sizeof(uint32_t), 1, binfile);
+
+ oldrootfslen = rootfslen;
+ if (args->pad_given) {
+ uint32_t allfs = 0xffffffff;
+ uint32_t pad_size = args->pad_arg * 1024 * 1024;
+
+ printf("Padding image to %d bytes ...\n", pad_size);
+ while (imagelen < pad_size) {
+ fwrite(&allfs, sizeof(uint32_t), 1, binfile);
+ imagelen += 4;
+ rootfslen += 4;
+ }
+ }
+
+ /* Flush the binfile buffer so that when we read from file, it contains
+ * everything in the buffer
+ */
+ fflush(binfile);
+
+ /* Compute the crc32 of the entire image (deadC0de included) */
+ imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr + cfelen, imagelen);
+ /* Compute the crc32 of the kernel and padding between kernel and rootfs) */
+ kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen);
+ /* Compute the crc32 of the kernel and padding between kernel and rootfs) */
+ kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode));
+ /* Compute the crc32 of the flashImageStart to rootLength.
+ * The broadcom firmware assumes the rootfs starts the image,
+ * therefore uses the rootfs start to determine where to flash
+ * the image. Since we have the kernel first we have to give
+ * it the kernel address, but the crc uses the length
+ * associated with this address, which is added to the kernel
+ * length to determine the length of image to flash and thus
+ * needs to be rootfs + deadcode
+ */
+ rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr + cfelen, rootfslen + sizeof(deadcode));
+
+ } else {
+ /* Build the kernel address and length (doesn't need to be aligned, read only) */
+ rootfsoff = fwaddr + sizeof(tag);
+ oldrootfslen = getlen(rootfsfile);
+ rootfslen = oldrootfslen;
+ rootfslen = ( (rootfslen % block_size) > 0 ? (((rootfslen / block_size) + 1) * block_size) : rootfslen );
+ kerneloffpadlen = rootfslen - oldrootfslen;
+ oldrootfslen = rootfslen;
+
+ kerneloff = rootfsoff + rootfslen;
+ kernellen = getlen(kernelfile);
+
+ imagelen = cfelen + rootfslen + kernellen;
+
+ /* Seek to the start of the kernel */
+ fseek(binfile, kerneloff - fwaddr + cfelen, SEEK_SET);
+
+ if (!args->kernel_file_has_header_flag) {
+ /* Build the kernel header */
+ khdr.loadaddr = htonl(load_address);
+ khdr.entry = htonl(entry);
+ khdr.lzmalen = htonl(kernellen);
+
+ /* Write the kernel header */
+ fwrite(&khdr, sizeof(khdr), 1, binfile);
+
+ /* Increase the kernel size by the header size */
+ kernellen += sizeof(khdr);
+ }
+
+ /* Write the kernel */
+ while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) {
+ read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), kernelfile);
+ fwrite(readbuf, sizeof(uint8_t), read, binfile);
+ }
+
+ /* Write the RootFS */
+ fseek(binfile, rootfsoff - fwaddr + cfelen, SEEK_SET);
+ while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) {
+ read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), rootfsfile);
+ fwrite(readbuf, sizeof(uint8_t), read, binfile);
+ }
+
+ /* Flush the binfile buffer so that when we read from file, it contains
+ * everything in the buffer
+ */
+ fflush(binfile);
+
+ /* Compute the crc32 of the entire image (deadC0de included) */
+ imagecrc = compute_crc32(imagecrc, binfile, sizeof(tag), imagelen);
+ /* Compute the crc32 of the kernel and padding between kernel and rootfs) */
+ kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen);
+ kernelfscrc = compute_crc32(kernelfscrc, binfile, rootfsoff - fwaddr + cfelen, kernellen + rootfslen);
+ rootfscrc = compute_crc32(rootfscrc, binfile, rootfsoff - fwaddr + cfelen, rootfslen);
+ }
+
+ /* Close the files */
+ if (cfefile) {
+ fclose(cfefile);
+ }
+ fclose(kernelfile);
+ fclose(rootfsfile);
+
+ /* Build the tag */
+ strncpy(tag.tagVersion, args->tag_version_arg, sizeof(tag.tagVersion) - 1);
+ strncpy(tag.sig_1, args->signature_arg, sizeof(tag.sig_1) - 1);
+ strncpy(tag.sig_2, args->signature2_arg, sizeof(tag.sig_2) - 1);
+ strncpy(tag.chipid, args->chipid_arg, sizeof(tag.chipid) - 1);
+ strncpy(tag.boardid, args->boardid_arg, sizeof(tag.boardid) - 1);
+ strcpy(tag.big_endian, "1");
+ sprintf(tag.totalLength, "%lu", imagelen);
+
+ if (args->cfe_given) {
+ sprintf(tag.cfeAddress, "%" PRIu32, flash_start);
+ sprintf(tag.cfeLength, "%lu", cfelen);
+ } else {
+ /* We don't include CFE */
+ strcpy(tag.cfeAddress, "0");
+ strcpy(tag.cfeLength, "0");
+ }
+
+ sprintf(tag.kernelAddress, "%lu", kerneloff);
+ sprintf(tag.kernelLength, "%lu", kernellen + rootfsoffpadlen);
+
+ if (args->root_first_flag) {
+ sprintf(tag.flashImageStart, "%lu", rootfsoff);
+ sprintf(tag.flashRootLength, "%lu", rootfslen);
+ } else {
+ sprintf(tag.flashImageStart, "%lu", kerneloff);
+ sprintf(tag.flashRootLength, "%lu", rootfslen + sizeof(deadcode));
+ }
+ int2tag(tag.rootLength, oldrootfslen + sizeof(deadcode));
+
+ if (args->rsa_signature_given) {
+ strncpy(tag.rsa_signature, args->rsa_signature_arg, RSASIG_LEN);
+ }
+
+ if (args->layoutver_given) {
+ strncpy(tag.flashLayoutVer, args->layoutver_arg, TAGLAYOUT_LEN);
+ }
+
+ if (args->info1_given) {
+ strncpy(tag.information1, args->info1_arg, TAGINFO1_LEN);
+ }
+
+ if (args->info2_given) {
+ strncpy(tag.information2, args->info2_arg, TAGINFO2_LEN);
+ }
+
+ if (args->reserved2_given) {
+ strncpy(tag.reserved2, args->reserved2_arg, 16);
+ }
+
+ if (args->altinfo_given) {
+ strncpy(tag.information1, args->altinfo_arg, TAGINFO1_LEN);
+ }
+
+ if (args->second_image_flag_given) {
+ if (strncmp(args->second_image_flag_arg, "2", DUALFLAG_LEN) != 0) {
+ strncpy(tag.dualImage, args->second_image_flag_arg, DUALFLAG_LEN);
+ }
+ }
+
+ if (args->inactive_given) {
+ if (strncmp(args->inactive_arg, "2", INACTIVEFLAG_LEN) != 0) {
+ strncpy(tag.inactiveFlag, args->second_image_flag_arg, INACTIVEFLAG_LEN);
+ }
+ }
+
+ for (i = 0; i < NUM_PIRELLI; i++) {
+ if (strncmp(args->boardid_arg, pirellitab[i], BOARDID_LEN) == 0) {
+ is_pirelli = 1;
+ break;
+ }
+ }
+
+ if ( !is_pirelli ) {
+ int2tag(tag.imageCRC, kernelfscrc);
+ } else {
+ int2tag(tag.imageCRC, kernelcrc);
+ }
+
+ int2tag(&(tag.rootfsCRC[0]), rootfscrc);
+ int2tag(tag.kernelCRC, kernelcrc);
+ int2tag(tag.fskernelCRC, kernelfscrc);
+ int2tag(tag.headerCRC, cyg_crc32_accumulate(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20));
+
+ fseek(binfile, 0L, SEEK_SET);
+ fwrite(&tag, sizeof(uint8_t), sizeof(tag), binfile);
+
+ fflush(binfile);
+ fclose(binfile);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int c, i;
+ char *kernel, *rootfs, *bin;
+ uint32_t flash_start, image_offset, block_size, load_address, entry;
+ flash_start = image_offset = block_size = load_address = entry = 0;
+ struct gengetopt_args_info parsed_args;
+
+ kernel = rootfs = bin = NULL;
+
+ if (imagetag_cmdline(argc, argv, &parsed_args)) {
+ exit(1);
+ }
+
+ printf("Broadcom 63xx image tagger - v2.0.0\n");
+ printf("Copyright (C) 2008 Axel Gembe\n");
+ printf("Copyright (C) 2009-2010 Daniel Dickinson\n");
+ printf("Licensed under the terms of the Gnu General Public License\n");
+
+ kernel = parsed_args.kernel_arg;
+ rootfs = parsed_args.rootfs_arg;
+ bin = parsed_args.output_arg;
+ if (strlen(parsed_args.tag_version_arg) >= TAGVER_LEN) {
+ fprintf(stderr, "Error: Tag Version (tag_version,v) too long.\n");
+ exit(1);
+ }
+ if (strlen(parsed_args.boardid_arg) >= BOARDID_LEN) {
+ fprintf(stderr, "Error: Board ID (boardid,b) too long.\n");
+ exit(1);
+ }
+ if (strlen(parsed_args.chipid_arg) >= CHIPID_LEN) {
+ fprintf(stderr, "Error: Chip ID (chipid,c) too long.\n");
+ exit(1);
+ }
+ if (strlen(parsed_args.signature_arg) >= SIG1_LEN) {
+ fprintf(stderr, "Error: Magic string (signature,a) too long.\n");
+ exit(1);
+ }
+ if (strlen(parsed_args.signature2_arg) >= SIG2_LEN) {
+ fprintf(stderr, "Error: Second magic string (signature2,m) too long.\n");
+ exit(1);
+ }
+ if (parsed_args.layoutver_given) {
+ if (strlen(parsed_args.layoutver_arg) > FLASHLAYOUTVER_LEN) {
+ fprintf(stderr, "Error: Flash layout version (layoutver,y) too long.\n");
+ exit(1);
+ }
+ }
+ if (parsed_args.rsa_signature_given) {
+ if (strlen(parsed_args.rsa_signature_arg) > RSASIG_LEN) {
+ fprintf(stderr, "Error: RSA Signature (rsa_signature,r) too long.\n");
+ exit(1);
+ }
+ }
+
+ if (parsed_args.info1_given) {
+ if (strlen(parsed_args.info1_arg) >= TAGINFO1_LEN) {
+ fprintf(stderr, "Error: Vendor Information 1 (info1) too long.\n");
+ exit(1);
+ }
+ }
+
+ if (parsed_args.info2_given) {
+ if (strlen(parsed_args.info2_arg) >= TAGINFO2_LEN) {
+ fprintf(stderr, "Error: Vendor Information 2 (info2) too long.\n");
+ exit(1);
+ }
+ }
+
+ if (parsed_args.altinfo_given) {
+ if (strlen(parsed_args.altinfo_arg) >= ALTTAGINFO_LEN) {
+ fprintf(stderr, "Error: Vendor Information 1 (info1) too long.\n");
+ exit(1);
+ }
+ }
+
+ if (parsed_args.pad_given) {
+ if (parsed_args.pad_arg < 0) {
+ fprintf(stderr, "Error: pad size must be positive.\r");
+ exit(1);
+ }
+ }
+
+ flash_start = strtoul(parsed_args.flash_start_arg, NULL, 16);
+ image_offset = strtoul(parsed_args.image_offset_arg, NULL, 16);
+ block_size = strtoul(parsed_args.block_size_arg, NULL, 16);
+
+ if (!parsed_args.kernel_file_has_header_flag) {
+ load_address = strtoul(parsed_args.load_addr_arg, NULL, 16);
+ entry = strtoul(parsed_args.entry_arg, NULL, 16);
+ if (load_address == 0) {
+ fprintf(stderr, "Error: Invalid value for load address\n");
+ }
+ if (entry == 0) {
+ fprintf(stderr, "Error: Invalid value for entry\n");
+ }
+ }
+
+ return tagfile(kernel, rootfs, bin, &parsed_args, flash_start, image_offset, block_size, load_address, entry);
+}
diff --git a/tools/firmware-utils/src/imagetag.ggo b/tools/firmware-utils/src/imagetag.ggo
new file mode 100644
index 0000000..7318485
--- /dev/null
+++ b/tools/firmware-utils/src/imagetag.ggo
@@ -0,0 +1,46 @@
+# Command line option parsing generator file for imagetag
+# Supplied-To: gengetopt
+#
+# Copyright 2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+
+package "imagetag"
+version "2.0.0"
+purpose "Generate image with CFE imagetag for Broadcom 63xx routers."
+description "Copyright (C) 2008 Axel Gembe
+Copyright (C) 2009-2010 Daniel Dickinson
+Licensed unter the terms of the Gnu General Public License.
+
+Given a root filesystem, a linux kernel, and an optional CFE, generates an image with an imagetag for a Broadcom 63xx-based router. Additional parameters to be specified depend on the specfic brand and model of router."
+args "--file-name=imagetag_cmdline"
+
+option "kernel" i "File with LZMA compressed kernel to include in the image." string typestr="filename" required
+option "rootfs" f "File with RootFS to include in the image." string typestr="filename" required
+option "output" o "Name of output file." string typestr="filename" required
+option "cfe" - "File with CFE to include in the image." string typestr="filename" optional
+option "boardid" b "Board ID to set in the image (must match what router expects, e.g. \"96345GW2\")." string required
+option "chipid" c "Chip ID to set in the image (must match the actual hardware, e.g. \"6345\")." string required
+option "flash-start" s "Flash start address." string typestr="address" optional default="0xBFC00000"
+option "image-offset" n "Offset from start address for the first byte after the CFE (in memory)." string typestr="offset" default="0x10000" optional
+option "tag-version" v "Version number for imagetag format." string default="6" optional
+option "signature" a "Magic string (signature), for boards that need it." string default="Broadcom Corporatio" optional
+option "signature2" m "Second magic string (signature2)." string default="ver. 2.0" optional
+option "block-size" k "Flash erase block size." string optional default="0x10000"
+option "load-addr" l "Kernel load address." string typestr="address" required
+option "entry" e "Address where the kernel entry point will be for booting." string typestr="address" required
+option "layoutver" y "Flash layout version (version 2.2x of the Broadcom code requires this)." string optional
+option "info1" 1 "String for first vendor information section." string optional
+option "altinfo" - "String for vendor information section (alternate/pirelli)." string optional
+option "info2" 2 "String for second vendor information section." string optional
+option "root-first" - "Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory)." flag off
+option "rsa-signature" r "String for RSA Signature section." string optional
+option "second-image-flag" - "Dual Image Flag (2=not-specified)." values="0", "1", "2" default="2" typestr="flag-value" optional
+option "inactive" - "Inactive Flag (2=not-specified)." values="0", "1", "2" default="2" typestr="flag-value" optional
+option "reserved2" - "String for second reserved section." string optional
+option "kernel-file-has-header" - "Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed" flag off
+option "pad" p "Pad the image to this size if smaller (in MiB)" int typestr="size (in MiB)" optional
+option "align-rootfs" - "Align the rootfs start to erase block size" flag off
diff --git a/tools/firmware-utils/src/imagetag_cmdline.c b/tools/firmware-utils/src/imagetag_cmdline.c
new file mode 100644
index 0000000..86c90bb
--- /dev/null
+++ b/tools/firmware-utils/src/imagetag_cmdline.c
@@ -0,0 +1,1193 @@
+/*
+ File autogenerated by gengetopt version 2.22.5
+ generated with the following command:
+ gengetopt -i imagetag.ggo -f imagetag_cmdline --file-name=imagetag_cmdline
+
+ The developers of gengetopt consider the fixed text that goes in all
+ gengetopt output files to be in the public domain:
+ we make no copyright claims on it.
+*/
+
+/* If we use autoconf. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef FIX_UNUSED
+#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
+#endif
+
+#include <getopt.h>
+
+#include "imagetag_cmdline.h"
+
+const char *gengetopt_args_info_purpose = "Generate image with CFE imagetag for Broadcom 63xx routers.";
+
+const char *gengetopt_args_info_usage = "Usage: imagetag [OPTIONS]...";
+
+const char *gengetopt_args_info_description = "Copyright (C) 2008 Axel Gembe\nCopyright (C) 2009-2010 Daniel Dickinson\nLicensed unter the terms of the Gnu General Public License.\n\nGiven a root filesystem, a linux kernel, and an optional CFE, generates an \nimage with an imagetag for a Broadcom 63xx-based router. Additional parameters \nto be specified depend on the specfic brand and model of router.";
+
+const char *gengetopt_args_info_help[] = {
+ " -h, --help Print help and exit",
+ " -V, --version Print version and exit",
+ " -i, --kernel=filename File with LZMA compressed kernel to include in \n the image.",
+ " -f, --rootfs=filename File with RootFS to include in the image.",
+ " -o, --output=filename Name of output file.",
+ " --cfe=filename File with CFE to include in the image.",
+ " -b, --boardid=STRING Board ID to set in the image (must match what \n router expects, e.g. \"96345GW2\").",
+ " -c, --chipid=STRING Chip ID to set in the image (must match the \n actual hardware, e.g. \"6345\").",
+ " -s, --flash-start=address Flash start address. (default=`0xBFC00000')",
+ " -n, --image-offset=offset Offset from start address for the first byte \n after the CFE (in memory). \n (default=`0x10000')",
+ " -v, --tag-version=STRING Version number for imagetag format. \n (default=`6')",
+ " -a, --signature=STRING Magic string (signature), for boards that need \n it. (default=`Broadcom Corporatio')",
+ " -m, --signature2=STRING Second magic string (signature2). \n (default=`ver. 2.0')",
+ " -k, --block-size=STRING Flash erase block size. (default=`0x10000')",
+ " -l, --load-addr=address Kernel load address.",
+ " -e, --entry=address Address where the kernel entry point will be \n for booting.",
+ " -y, --layoutver=STRING Flash layout version (version 2.2x of the \n Broadcom code requires this).",
+ " -1, --info1=STRING String for first vendor information section.",
+ " --altinfo=STRING String for vendor information section \n (alternate/pirelli).",
+ " -2, --info2=STRING String for second vendor information section.",
+ " --root-first Put the rootfs before the kernel (only for \n stock images, e.g. captured from the router's \n flash memory). (default=off)",
+ " -r, --rsa-signature=STRING String for RSA Signature section.",
+ " --second-image-flag=flag-value\n Dual Image Flag (2=not-specified). (possible \n values=\"0\", \"1\", \"2\" default=`2')",
+ " --inactive=flag-value Inactive Flag (2=not-specified). (possible \n values=\"0\", \"1\", \"2\" default=`2')",
+ " --reserved2=STRING String for second reserved section.",
+ " --kernel-file-has-header Indicates that the kernel file includes the \n kernel header with correct load address and \n entry point, so no changes are needed \n (default=off)",
+ " -p, --pad=size (in MiB) Pad the image to this size if smaller (in MiB)",
+ " --align-rootfs Align the rootfs start to erase block size \n (default=off)",
+ 0
+};
+
+typedef enum {ARG_NO
+ , ARG_FLAG
+ , ARG_STRING
+ , ARG_INT
+} imagetag_cmdline_arg_type;
+
+static
+void clear_given (struct gengetopt_args_info *args_info);
+static
+void clear_args (struct gengetopt_args_info *args_info);
+
+static int
+imagetag_cmdline_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
+ struct imagetag_cmdline_params *params, const char *additional_error);
+
+static int
+imagetag_cmdline_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
+
+const char *imagetag_cmdline_second_image_flag_values[] = {"0", "1", "2", 0}; /*< Possible values for second-image-flag. */
+const char *imagetag_cmdline_inactive_values[] = {"0", "1", "2", 0}; /*< Possible values for inactive. */
+
+static char *
+gengetopt_strdup (const char *s);
+
+static
+void clear_given (struct gengetopt_args_info *args_info)
+{
+ args_info->help_given = 0 ;
+ args_info->version_given = 0 ;
+ args_info->kernel_given = 0 ;
+ args_info->rootfs_given = 0 ;
+ args_info->output_given = 0 ;
+ args_info->cfe_given = 0 ;
+ args_info->boardid_given = 0 ;
+ args_info->chipid_given = 0 ;
+ args_info->flash_start_given = 0 ;
+ args_info->image_offset_given = 0 ;
+ args_info->tag_version_given = 0 ;
+ args_info->signature_given = 0 ;
+ args_info->signature2_given = 0 ;
+ args_info->block_size_given = 0 ;
+ args_info->load_addr_given = 0 ;
+ args_info->entry_given = 0 ;
+ args_info->layoutver_given = 0 ;
+ args_info->info1_given = 0 ;
+ args_info->altinfo_given = 0 ;
+ args_info->info2_given = 0 ;
+ args_info->root_first_given = 0 ;
+ args_info->rsa_signature_given = 0 ;
+ args_info->second_image_flag_given = 0 ;
+ args_info->inactive_given = 0 ;
+ args_info->reserved2_given = 0 ;
+ args_info->kernel_file_has_header_given = 0 ;
+ args_info->pad_given = 0 ;
+ args_info->align_rootfs_given = 0 ;
+}
+
+static
+void clear_args (struct gengetopt_args_info *args_info)
+{
+ FIX_UNUSED (args_info);
+ args_info->kernel_arg = NULL;
+ args_info->kernel_orig = NULL;
+ args_info->rootfs_arg = NULL;
+ args_info->rootfs_orig = NULL;
+ args_info->output_arg = NULL;
+ args_info->output_orig = NULL;
+ args_info->cfe_arg = NULL;
+ args_info->cfe_orig = NULL;
+ args_info->boardid_arg = NULL;
+ args_info->boardid_orig = NULL;
+ args_info->chipid_arg = NULL;
+ args_info->chipid_orig = NULL;
+ args_info->flash_start_arg = gengetopt_strdup ("0xBFC00000");
+ args_info->flash_start_orig = NULL;
+ args_info->image_offset_arg = gengetopt_strdup ("0x10000");
+ args_info->image_offset_orig = NULL;
+ args_info->tag_version_arg = gengetopt_strdup ("6");
+ args_info->tag_version_orig = NULL;
+ args_info->signature_arg = gengetopt_strdup ("Broadcom Corporatio");
+ args_info->signature_orig = NULL;
+ args_info->signature2_arg = gengetopt_strdup ("ver. 2.0");
+ args_info->signature2_orig = NULL;
+ args_info->block_size_arg = gengetopt_strdup ("0x10000");
+ args_info->block_size_orig = NULL;
+ args_info->load_addr_arg = NULL;
+ args_info->load_addr_orig = NULL;
+ args_info->entry_arg = NULL;
+ args_info->entry_orig = NULL;
+ args_info->layoutver_arg = NULL;
+ args_info->layoutver_orig = NULL;
+ args_info->info1_arg = NULL;
+ args_info->info1_orig = NULL;
+ args_info->altinfo_arg = NULL;
+ args_info->altinfo_orig = NULL;
+ args_info->info2_arg = NULL;
+ args_info->info2_orig = NULL;
+ args_info->root_first_flag = 0;
+ args_info->rsa_signature_arg = NULL;
+ args_info->rsa_signature_orig = NULL;
+ args_info->second_image_flag_arg = gengetopt_strdup ("2");
+ args_info->second_image_flag_orig = NULL;
+ args_info->inactive_arg = gengetopt_strdup ("2");
+ args_info->inactive_orig = NULL;
+ args_info->reserved2_arg = NULL;
+ args_info->reserved2_orig = NULL;
+ args_info->kernel_file_has_header_flag = 0;
+ args_info->pad_orig = NULL;
+ args_info->align_rootfs_flag = 0;
+
+}
+
+static
+void init_args_info(struct gengetopt_args_info *args_info)
+{
+
+
+ args_info->help_help = gengetopt_args_info_help[0] ;
+ args_info->version_help = gengetopt_args_info_help[1] ;
+ args_info->kernel_help = gengetopt_args_info_help[2] ;
+ args_info->rootfs_help = gengetopt_args_info_help[3] ;
+ args_info->output_help = gengetopt_args_info_help[4] ;
+ args_info->cfe_help = gengetopt_args_info_help[5] ;
+ args_info->boardid_help = gengetopt_args_info_help[6] ;
+ args_info->chipid_help = gengetopt_args_info_help[7] ;
+ args_info->flash_start_help = gengetopt_args_info_help[8] ;
+ args_info->image_offset_help = gengetopt_args_info_help[9] ;
+ args_info->tag_version_help = gengetopt_args_info_help[10] ;
+ args_info->signature_help = gengetopt_args_info_help[11] ;
+ args_info->signature2_help = gengetopt_args_info_help[12] ;
+ args_info->block_size_help = gengetopt_args_info_help[13] ;
+ args_info->load_addr_help = gengetopt_args_info_help[14] ;
+ args_info->entry_help = gengetopt_args_info_help[15] ;
+ args_info->layoutver_help = gengetopt_args_info_help[16] ;
+ args_info->info1_help = gengetopt_args_info_help[17] ;
+ args_info->altinfo_help = gengetopt_args_info_help[18] ;
+ args_info->info2_help = gengetopt_args_info_help[19] ;
+ args_info->root_first_help = gengetopt_args_info_help[20] ;
+ args_info->rsa_signature_help = gengetopt_args_info_help[21] ;
+ args_info->second_image_flag_help = gengetopt_args_info_help[22] ;
+ args_info->inactive_help = gengetopt_args_info_help[23] ;
+ args_info->reserved2_help = gengetopt_args_info_help[24] ;
+ args_info->kernel_file_has_header_help = gengetopt_args_info_help[25] ;
+ args_info->pad_help = gengetopt_args_info_help[26] ;
+ args_info->align_rootfs_help = gengetopt_args_info_help[27] ;
+
+}
+
+void
+imagetag_cmdline_print_version (void)
+{
+ printf ("%s %s\n",
+ (strlen(IMAGETAG_CMDLINE_PACKAGE_NAME) ? IMAGETAG_CMDLINE_PACKAGE_NAME : IMAGETAG_CMDLINE_PACKAGE),
+ IMAGETAG_CMDLINE_VERSION);
+}
+
+static void print_help_common(void) {
+ imagetag_cmdline_print_version ();
+
+ if (strlen(gengetopt_args_info_purpose) > 0)
+ printf("\n%s\n", gengetopt_args_info_purpose);
+
+ if (strlen(gengetopt_args_info_usage) > 0)
+ printf("\n%s\n", gengetopt_args_info_usage);
+
+ printf("\n");
+
+ if (strlen(gengetopt_args_info_description) > 0)
+ printf("%s\n\n", gengetopt_args_info_description);
+}
+
+void
+imagetag_cmdline_print_help (void)
+{
+ int i = 0;
+ print_help_common();
+ while (gengetopt_args_info_help[i])
+ printf("%s\n", gengetopt_args_info_help[i++]);
+}
+
+void
+imagetag_cmdline_init (struct gengetopt_args_info *args_info)
+{
+ clear_given (args_info);
+ clear_args (args_info);
+ init_args_info (args_info);
+}
+
+void
+imagetag_cmdline_params_init(struct imagetag_cmdline_params *params)
+{
+ if (params)
+ {
+ params->override = 0;
+ params->initialize = 1;
+ params->check_required = 1;
+ params->check_ambiguity = 0;
+ params->print_errors = 1;
+ }
+}
+
+struct imagetag_cmdline_params *
+imagetag_cmdline_params_create(void)
+{
+ struct imagetag_cmdline_params *params =
+ (struct imagetag_cmdline_params *)malloc(sizeof(struct imagetag_cmdline_params));
+ imagetag_cmdline_params_init(params);
+ return params;
+}
+
+static void
+free_string_field (char **s)
+{
+ if (*s)
+ {
+ free (*s);
+ *s = 0;
+ }
+}
+
+
+static void
+imagetag_cmdline_release (struct gengetopt_args_info *args_info)
+{
+
+ free_string_field (&(args_info->kernel_arg));
+ free_string_field (&(args_info->kernel_orig));
+ free_string_field (&(args_info->rootfs_arg));
+ free_string_field (&(args_info->rootfs_orig));
+ free_string_field (&(args_info->output_arg));
+ free_string_field (&(args_info->output_orig));
+ free_string_field (&(args_info->cfe_arg));
+ free_string_field (&(args_info->cfe_orig));
+ free_string_field (&(args_info->boardid_arg));
+ free_string_field (&(args_info->boardid_orig));
+ free_string_field (&(args_info->chipid_arg));
+ free_string_field (&(args_info->chipid_orig));
+ free_string_field (&(args_info->flash_start_arg));
+ free_string_field (&(args_info->flash_start_orig));
+ free_string_field (&(args_info->image_offset_arg));
+ free_string_field (&(args_info->image_offset_orig));
+ free_string_field (&(args_info->tag_version_arg));
+ free_string_field (&(args_info->tag_version_orig));
+ free_string_field (&(args_info->signature_arg));
+ free_string_field (&(args_info->signature_orig));
+ free_string_field (&(args_info->signature2_arg));
+ free_string_field (&(args_info->signature2_orig));
+ free_string_field (&(args_info->block_size_arg));
+ free_string_field (&(args_info->block_size_orig));
+ free_string_field (&(args_info->load_addr_arg));
+ free_string_field (&(args_info->load_addr_orig));
+ free_string_field (&(args_info->entry_arg));
+ free_string_field (&(args_info->entry_orig));
+ free_string_field (&(args_info->layoutver_arg));
+ free_string_field (&(args_info->layoutver_orig));
+ free_string_field (&(args_info->info1_arg));
+ free_string_field (&(args_info->info1_orig));
+ free_string_field (&(args_info->altinfo_arg));
+ free_string_field (&(args_info->altinfo_orig));
+ free_string_field (&(args_info->info2_arg));
+ free_string_field (&(args_info->info2_orig));
+ free_string_field (&(args_info->rsa_signature_arg));
+ free_string_field (&(args_info->rsa_signature_orig));
+ free_string_field (&(args_info->second_image_flag_arg));
+ free_string_field (&(args_info->second_image_flag_orig));
+ free_string_field (&(args_info->inactive_arg));
+ free_string_field (&(args_info->inactive_orig));
+ free_string_field (&(args_info->reserved2_arg));
+ free_string_field (&(args_info->reserved2_orig));
+ free_string_field (&(args_info->pad_orig));
+
+
+
+ clear_given (args_info);
+}
+
+/**
+ * @param val the value to check
+ * @param values the possible values
+ * @return the index of the matched value:
+ * -1 if no value matched,
+ * -2 if more than one value has matched
+ */
+static int
+check_possible_values(const char *val, const char *values[])
+{
+ int i, found, last;
+ size_t len;
+
+ if (!val) /* otherwise strlen() crashes below */
+ return -1; /* -1 means no argument for the option */
+
+ found = last = 0;
+
+ for (i = 0, len = strlen(val); values[i]; ++i)
+ {
+ if (strncmp(val, values[i], len) == 0)
+ {
+ ++found;
+ last = i;
+ if (strlen(values[i]) == len)
+ return i; /* exact macth no need to check more */
+ }
+ }
+
+ if (found == 1) /* one match: OK */
+ return last;
+
+ return (found ? -2 : -1); /* return many values or none matched */
+}
+
+
+static void
+write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
+{
+ int found = -1;
+ if (arg) {
+ if (values) {
+ found = check_possible_values(arg, values);
+ }
+ if (found >= 0)
+ fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]);
+ else
+ fprintf(outfile, "%s=\"%s\"\n", opt, arg);
+ } else {
+ fprintf(outfile, "%s\n", opt);
+ }
+}
+
+
+int
+imagetag_cmdline_dump(FILE *outfile, struct gengetopt_args_info *args_info)
+{
+ int i = 0;
+
+ if (!outfile)
+ {
+ fprintf (stderr, "%s: cannot dump options to stream\n", IMAGETAG_CMDLINE_PACKAGE);
+ return EXIT_FAILURE;
+ }
+
+ if (args_info->help_given)
+ write_into_file(outfile, "help", 0, 0 );
+ if (args_info->version_given)
+ write_into_file(outfile, "version", 0, 0 );
+ if (args_info->kernel_given)
+ write_into_file(outfile, "kernel", args_info->kernel_orig, 0);
+ if (args_info->rootfs_given)
+ write_into_file(outfile, "rootfs", args_info->rootfs_orig, 0);
+ if (args_info->output_given)
+ write_into_file(outfile, "output", args_info->output_orig, 0);
+ if (args_info->cfe_given)
+ write_into_file(outfile, "cfe", args_info->cfe_orig, 0);
+ if (args_info->boardid_given)
+ write_into_file(outfile, "boardid", args_info->boardid_orig, 0);
+ if (args_info->chipid_given)
+ write_into_file(outfile, "chipid", args_info->chipid_orig, 0);
+ if (args_info->flash_start_given)
+ write_into_file(outfile, "flash-start", args_info->flash_start_orig, 0);
+ if (args_info->image_offset_given)
+ write_into_file(outfile, "image-offset", args_info->image_offset_orig, 0);
+ if (args_info->tag_version_given)
+ write_into_file(outfile, "tag-version", args_info->tag_version_orig, 0);
+ if (args_info->signature_given)
+ write_into_file(outfile, "signature", args_info->signature_orig, 0);
+ if (args_info->signature2_given)
+ write_into_file(outfile, "signature2", args_info->signature2_orig, 0);
+ if (args_info->block_size_given)
+ write_into_file(outfile, "block-size", args_info->block_size_orig, 0);
+ if (args_info->load_addr_given)
+ write_into_file(outfile, "load-addr", args_info->load_addr_orig, 0);
+ if (args_info->entry_given)
+ write_into_file(outfile, "entry", args_info->entry_orig, 0);
+ if (args_info->layoutver_given)
+ write_into_file(outfile, "layoutver", args_info->layoutver_orig, 0);
+ if (args_info->info1_given)
+ write_into_file(outfile, "info1", args_info->info1_orig, 0);
+ if (args_info->altinfo_given)
+ write_into_file(outfile, "altinfo", args_info->altinfo_orig, 0);
+ if (args_info->info2_given)
+ write_into_file(outfile, "info2", args_info->info2_orig, 0);
+ if (args_info->root_first_given)
+ write_into_file(outfile, "root-first", 0, 0 );
+ if (args_info->rsa_signature_given)
+ write_into_file(outfile, "rsa-signature", args_info->rsa_signature_orig, 0);
+ if (args_info->second_image_flag_given)
+ write_into_file(outfile, "second-image-flag", args_info->second_image_flag_orig, imagetag_cmdline_second_image_flag_values);
+ if (args_info->inactive_given)
+ write_into_file(outfile, "inactive", args_info->inactive_orig, imagetag_cmdline_inactive_values);
+ if (args_info->reserved2_given)
+ write_into_file(outfile, "reserved2", args_info->reserved2_orig, 0);
+ if (args_info->kernel_file_has_header_given)
+ write_into_file(outfile, "kernel-file-has-header", 0, 0 );
+ if (args_info->pad_given)
+ write_into_file(outfile, "pad", args_info->pad_orig, 0);
+ if (args_info->align_rootfs_given)
+ write_into_file(outfile, "align-rootfs", 0, 0 );
+
+
+ i = EXIT_SUCCESS;
+ return i;
+}
+
+int
+imagetag_cmdline_file_save(const char *filename, struct gengetopt_args_info *args_info)
+{
+ FILE *outfile;
+ int i = 0;
+
+ outfile = fopen(filename, "w");
+
+ if (!outfile)
+ {
+ fprintf (stderr, "%s: cannot open file for writing: %s\n", IMAGETAG_CMDLINE_PACKAGE, filename);
+ return EXIT_FAILURE;
+ }
+
+ i = imagetag_cmdline_dump(outfile, args_info);
+ fclose (outfile);
+
+ return i;
+}
+
+void
+imagetag_cmdline_free (struct gengetopt_args_info *args_info)
+{
+ imagetag_cmdline_release (args_info);
+}
+
+/** @brief replacement of strdup, which is not standard */
+char *
+gengetopt_strdup (const char *s)
+{
+ char *result = 0;
+ if (!s)
+ return result;
+
+ result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+
+int
+imagetag_cmdline (int argc, char **argv, struct gengetopt_args_info *args_info)
+{
+ return imagetag_cmdline2 (argc, argv, args_info, 0, 1, 1);
+}
+
+int
+imagetag_cmdline_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
+ struct imagetag_cmdline_params *params)
+{
+ int result;
+ result = imagetag_cmdline_internal (argc, argv, args_info, params, 0);
+
+ if (result == EXIT_FAILURE)
+ {
+ imagetag_cmdline_free (args_info);
+ exit (EXIT_FAILURE);
+ }
+
+ return result;
+}
+
+int
+imagetag_cmdline2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+{
+ int result;
+ struct imagetag_cmdline_params params;
+
+ params.override = override;
+ params.initialize = initialize;
+ params.check_required = check_required;
+ params.check_ambiguity = 0;
+ params.print_errors = 1;
+
+ result = imagetag_cmdline_internal (argc, argv, args_info, &params, 0);
+
+ if (result == EXIT_FAILURE)
+ {
+ imagetag_cmdline_free (args_info);
+ exit (EXIT_FAILURE);
+ }
+
+ return result;
+}
+
+int
+imagetag_cmdline_required (struct gengetopt_args_info *args_info, const char *prog_name)
+{
+ int result = EXIT_SUCCESS;
+
+ if (imagetag_cmdline_required2(args_info, prog_name, 0) > 0)
+ result = EXIT_FAILURE;
+
+ if (result == EXIT_FAILURE)
+ {
+ imagetag_cmdline_free (args_info);
+ exit (EXIT_FAILURE);
+ }
+
+ return result;
+}
+
+int
+imagetag_cmdline_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
+{
+ int error = 0;
+ FIX_UNUSED (additional_error);
+
+ /* checks for required options */
+ if (! args_info->kernel_given)
+ {
+ fprintf (stderr, "%s: '--kernel' ('-i') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+ if (! args_info->rootfs_given)
+ {
+ fprintf (stderr, "%s: '--rootfs' ('-f') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+ if (! args_info->output_given)
+ {
+ fprintf (stderr, "%s: '--output' ('-o') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+ if (! args_info->boardid_given)
+ {
+ fprintf (stderr, "%s: '--boardid' ('-b') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+ if (! args_info->chipid_given)
+ {
+ fprintf (stderr, "%s: '--chipid' ('-c') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+ if (! args_info->load_addr_given)
+ {
+ fprintf (stderr, "%s: '--load-addr' ('-l') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+ if (! args_info->entry_given)
+ {
+ fprintf (stderr, "%s: '--entry' ('-e') option required%s\n", prog_name, (additional_error ? additional_error : ""));
+ error = 1;
+ }
+
+
+ /* checks for dependences among options */
+
+ return error;
+}
+
+
+static char *package_name = 0;
+
+/**
+ * @brief updates an option
+ * @param field the generic pointer to the field to update
+ * @param orig_field the pointer to the orig field
+ * @param field_given the pointer to the number of occurrence of this option
+ * @param prev_given the pointer to the number of occurrence already seen
+ * @param value the argument for this option (if null no arg was specified)
+ * @param possible_values the possible values for this option (if specified)
+ * @param default_value the default value (in case the option only accepts fixed values)
+ * @param arg_type the type of this option
+ * @param check_ambiguity @see imagetag_cmdline_params.check_ambiguity
+ * @param override @see imagetag_cmdline_params.override
+ * @param no_free whether to free a possible previous value
+ * @param multiple_option whether this is a multiple option
+ * @param long_opt the corresponding long option
+ * @param short_opt the corresponding short option (or '-' if none)
+ * @param additional_error possible further error specification
+ */
+static
+int update_arg(void *field, char **orig_field,
+ unsigned int *field_given, unsigned int *prev_given,
+ char *value, const char *possible_values[],
+ const char *default_value,
+ imagetag_cmdline_arg_type arg_type,
+ int check_ambiguity, int override,
+ int no_free, int multiple_option,
+ const char *long_opt, char short_opt,
+ const char *additional_error)
+{
+ char *stop_char = 0;
+ const char *val = value;
+ int found;
+ char **string_field;
+ FIX_UNUSED (field);
+
+ stop_char = 0;
+ found = 0;
+
+ if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
+ {
+ if (short_opt != '-')
+ fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
+ package_name, long_opt, short_opt,
+ (additional_error ? additional_error : ""));
+ else
+ fprintf (stderr, "%s: `--%s' option given more than once%s\n",
+ package_name, long_opt,
+ (additional_error ? additional_error : ""));
+ return 1; /* failure */
+ }
+
+ if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0)
+ {
+ if (short_opt != '-')
+ fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n",
+ package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt,
+ (additional_error ? additional_error : ""));
+ else
+ fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n",
+ package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt,
+ (additional_error ? additional_error : ""));
+ return 1; /* failure */
+ }
+
+ if (field_given && *field_given && ! override)
+ return 0;
+ if (prev_given)
+ (*prev_given)++;
+ if (field_given)
+ (*field_given)++;
+ if (possible_values)
+ val = possible_values[found];
+
+ switch(arg_type) {
+ case ARG_FLAG:
+ *((int *)field) = !*((int *)field);
+ break;
+ case ARG_INT:
+ if (val) *((int *)field) = strtol (val, &stop_char, 0);
+ break;
+ case ARG_STRING:
+ if (val) {
+ string_field = (char **)field;
+ if (!no_free && *string_field)
+ free (*string_field); /* free previous string */
+ *string_field = gengetopt_strdup (val);
+ }
+ break;
+ default:
+ break;
+ };
+
+ /* check numeric conversion */
+ switch(arg_type) {
+ case ARG_INT:
+ if (val && !(stop_char && *stop_char == '\0')) {
+ fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
+ return 1; /* failure */
+ }
+ break;
+ default:
+ ;
+ };
+
+ /* store the original value */
+ switch(arg_type) {
+ case ARG_NO:
+ case ARG_FLAG:
+ break;
+ default:
+ if (value && orig_field) {
+ if (no_free) {
+ *orig_field = value;
+ } else {
+ if (*orig_field)
+ free (*orig_field); /* free previous string */
+ *orig_field = gengetopt_strdup (value);
+ }
+ }
+ };
+
+ return 0; /* OK */
+}
+
+
+int
+imagetag_cmdline_internal (
+ int argc, char **argv, struct gengetopt_args_info *args_info,
+ struct imagetag_cmdline_params *params, const char *additional_error)
+{
+ int c; /* Character of the parsed option. */
+
+ int error = 0;
+ struct gengetopt_args_info local_args_info;
+
+ int override;
+ int initialize;
+ int check_required;
+ int check_ambiguity;
+
+ package_name = argv[0];
+
+ override = params->override;
+ initialize = params->initialize;
+ check_required = params->check_required;
+ check_ambiguity = params->check_ambiguity;
+
+ if (initialize)
+ imagetag_cmdline_init (args_info);
+
+ imagetag_cmdline_init (&local_args_info);
+
+ optarg = 0;
+ optind = 0;
+ opterr = params->print_errors;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "kernel", 1, NULL, 'i' },
+ { "rootfs", 1, NULL, 'f' },
+ { "output", 1, NULL, 'o' },
+ { "cfe", 1, NULL, 0 },
+ { "boardid", 1, NULL, 'b' },
+ { "chipid", 1, NULL, 'c' },
+ { "flash-start", 1, NULL, 's' },
+ { "image-offset", 1, NULL, 'n' },
+ { "tag-version", 1, NULL, 'v' },
+ { "signature", 1, NULL, 'a' },
+ { "signature2", 1, NULL, 'm' },
+ { "block-size", 1, NULL, 'k' },
+ { "load-addr", 1, NULL, 'l' },
+ { "entry", 1, NULL, 'e' },
+ { "layoutver", 1, NULL, 'y' },
+ { "info1", 1, NULL, '1' },
+ { "altinfo", 1, NULL, 0 },
+ { "info2", 1, NULL, '2' },
+ { "root-first", 0, NULL, 0 },
+ { "rsa-signature", 1, NULL, 'r' },
+ { "second-image-flag", 1, NULL, 0 },
+ { "inactive", 1, NULL, 0 },
+ { "reserved2", 1, NULL, 0 },
+ { "kernel-file-has-header", 0, NULL, 0 },
+ { "pad", 1, NULL, 'p' },
+ { "align-rootfs", 0, NULL, 0 },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long (argc, argv, "hVi:f:o:b:c:s:n:v:a:m:k:l:e:y:1:2:r:p:", long_options, &option_index);
+
+ if (c == -1) break; /* Exit from `while (1)' loop. */
+
+ switch (c)
+ {
+ case 'h': /* Print help and exit. */
+ imagetag_cmdline_print_help ();
+ imagetag_cmdline_free (&local_args_info);
+ exit (EXIT_SUCCESS);
+
+ case 'V': /* Print version and exit. */
+ imagetag_cmdline_print_version ();
+ imagetag_cmdline_free (&local_args_info);
+ exit (EXIT_SUCCESS);
+
+ case 'i': /* File with LZMA compressed kernel to include in the image.. */
+
+
+ if (update_arg( (void *)&(args_info->kernel_arg),
+ &(args_info->kernel_orig), &(args_info->kernel_given),
+ &(local_args_info.kernel_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "kernel", 'i',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'f': /* File with RootFS to include in the image.. */
+
+
+ if (update_arg( (void *)&(args_info->rootfs_arg),
+ &(args_info->rootfs_orig), &(args_info->rootfs_given),
+ &(local_args_info.rootfs_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "rootfs", 'f',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'o': /* Name of output file.. */
+
+
+ if (update_arg( (void *)&(args_info->output_arg),
+ &(args_info->output_orig), &(args_info->output_given),
+ &(local_args_info.output_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "output", 'o',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'b': /* Board ID to set in the image (must match what router expects, e.g. \"96345GW2\").. */
+
+
+ if (update_arg( (void *)&(args_info->boardid_arg),
+ &(args_info->boardid_orig), &(args_info->boardid_given),
+ &(local_args_info.boardid_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "boardid", 'b',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'c': /* Chip ID to set in the image (must match the actual hardware, e.g. \"6345\").. */
+
+
+ if (update_arg( (void *)&(args_info->chipid_arg),
+ &(args_info->chipid_orig), &(args_info->chipid_given),
+ &(local_args_info.chipid_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "chipid", 'c',
+ additional_error))
+ goto failure;
+
+ break;
+ case 's': /* Flash start address.. */
+
+
+ if (update_arg( (void *)&(args_info->flash_start_arg),
+ &(args_info->flash_start_orig), &(args_info->flash_start_given),
+ &(local_args_info.flash_start_given), optarg, 0, "0xBFC00000", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "flash-start", 's',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'n': /* Offset from start address for the first byte after the CFE (in memory).. */
+
+
+ if (update_arg( (void *)&(args_info->image_offset_arg),
+ &(args_info->image_offset_orig), &(args_info->image_offset_given),
+ &(local_args_info.image_offset_given), optarg, 0, "0x10000", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "image-offset", 'n',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'v': /* Version number for imagetag format.. */
+
+
+ if (update_arg( (void *)&(args_info->tag_version_arg),
+ &(args_info->tag_version_orig), &(args_info->tag_version_given),
+ &(local_args_info.tag_version_given), optarg, 0, "6", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "tag-version", 'v',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'a': /* Magic string (signature), for boards that need it.. */
+
+
+ if (update_arg( (void *)&(args_info->signature_arg),
+ &(args_info->signature_orig), &(args_info->signature_given),
+ &(local_args_info.signature_given), optarg, 0, "Broadcom Corporatio", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "signature", 'a',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'm': /* Second magic string (signature2).. */
+
+
+ if (update_arg( (void *)&(args_info->signature2_arg),
+ &(args_info->signature2_orig), &(args_info->signature2_given),
+ &(local_args_info.signature2_given), optarg, 0, "ver. 2.0", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "signature2", 'm',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'k': /* Flash erase block size.. */
+
+
+ if (update_arg( (void *)&(args_info->block_size_arg),
+ &(args_info->block_size_orig), &(args_info->block_size_given),
+ &(local_args_info.block_size_given), optarg, 0, "0x10000", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "block-size", 'k',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'l': /* Kernel load address.. */
+
+
+ if (update_arg( (void *)&(args_info->load_addr_arg),
+ &(args_info->load_addr_orig), &(args_info->load_addr_given),
+ &(local_args_info.load_addr_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "load-addr", 'l',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'e': /* Address where the kernel entry point will be for booting.. */
+
+
+ if (update_arg( (void *)&(args_info->entry_arg),
+ &(args_info->entry_orig), &(args_info->entry_given),
+ &(local_args_info.entry_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "entry", 'e',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'y': /* Flash layout version (version 2.2x of the Broadcom code requires this).. */
+
+
+ if (update_arg( (void *)&(args_info->layoutver_arg),
+ &(args_info->layoutver_orig), &(args_info->layoutver_given),
+ &(local_args_info.layoutver_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "layoutver", 'y',
+ additional_error))
+ goto failure;
+
+ break;
+ case '1': /* String for first vendor information section.. */
+
+
+ if (update_arg( (void *)&(args_info->info1_arg),
+ &(args_info->info1_orig), &(args_info->info1_given),
+ &(local_args_info.info1_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "info1", '1',
+ additional_error))
+ goto failure;
+
+ break;
+ case '2': /* String for second vendor information section.. */
+
+
+ if (update_arg( (void *)&(args_info->info2_arg),
+ &(args_info->info2_orig), &(args_info->info2_given),
+ &(local_args_info.info2_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "info2", '2',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'r': /* String for RSA Signature section.. */
+
+
+ if (update_arg( (void *)&(args_info->rsa_signature_arg),
+ &(args_info->rsa_signature_orig), &(args_info->rsa_signature_given),
+ &(local_args_info.rsa_signature_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "rsa-signature", 'r',
+ additional_error))
+ goto failure;
+
+ break;
+ case 'p': /* Pad the image to this size if smaller (in MiB). */
+
+
+ if (update_arg( (void *)&(args_info->pad_arg),
+ &(args_info->pad_orig), &(args_info->pad_given),
+ &(local_args_info.pad_given), optarg, 0, 0, ARG_INT,
+ check_ambiguity, override, 0, 0,
+ "pad", 'p',
+ additional_error))
+ goto failure;
+
+ break;
+
+ case 0: /* Long option with no short option */
+ /* File with CFE to include in the image.. */
+ if (strcmp (long_options[option_index].name, "cfe") == 0)
+ {
+
+
+ if (update_arg( (void *)&(args_info->cfe_arg),
+ &(args_info->cfe_orig), &(args_info->cfe_given),
+ &(local_args_info.cfe_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "cfe", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* String for vendor information section (alternate/pirelli).. */
+ else if (strcmp (long_options[option_index].name, "altinfo") == 0)
+ {
+
+
+ if (update_arg( (void *)&(args_info->altinfo_arg),
+ &(args_info->altinfo_orig), &(args_info->altinfo_given),
+ &(local_args_info.altinfo_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "altinfo", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory).. */
+ else if (strcmp (long_options[option_index].name, "root-first") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->root_first_flag), 0, &(args_info->root_first_given),
+ &(local_args_info.root_first_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "root-first", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Dual Image Flag (2=not-specified).. */
+ else if (strcmp (long_options[option_index].name, "second-image-flag") == 0)
+ {
+
+
+ if (update_arg( (void *)&(args_info->second_image_flag_arg),
+ &(args_info->second_image_flag_orig), &(args_info->second_image_flag_given),
+ &(local_args_info.second_image_flag_given), optarg, imagetag_cmdline_second_image_flag_values, "2", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "second-image-flag", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Inactive Flag (2=not-specified).. */
+ else if (strcmp (long_options[option_index].name, "inactive") == 0)
+ {
+
+
+ if (update_arg( (void *)&(args_info->inactive_arg),
+ &(args_info->inactive_orig), &(args_info->inactive_given),
+ &(local_args_info.inactive_given), optarg, imagetag_cmdline_inactive_values, "2", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "inactive", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* String for second reserved section.. */
+ else if (strcmp (long_options[option_index].name, "reserved2") == 0)
+ {
+
+
+ if (update_arg( (void *)&(args_info->reserved2_arg),
+ &(args_info->reserved2_orig), &(args_info->reserved2_given),
+ &(local_args_info.reserved2_given), optarg, 0, 0, ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "reserved2", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed. */
+ else if (strcmp (long_options[option_index].name, "kernel-file-has-header") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->kernel_file_has_header_flag), 0, &(args_info->kernel_file_has_header_given),
+ &(local_args_info.kernel_file_has_header_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "kernel-file-has-header", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Align the rootfs start to erase block size. */
+ else if (strcmp (long_options[option_index].name, "align-rootfs") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->align_rootfs_flag), 0, &(args_info->align_rootfs_given),
+ &(local_args_info.align_rootfs_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "align-rootfs", '-',
+ additional_error))
+ goto failure;
+
+ }
+
+ break;
+ case '?': /* Invalid option. */
+ /* `getopt_long' already printed an error message. */
+ goto failure;
+
+ default: /* bug: option not considered. */
+ fprintf (stderr, "%s: option unknown: %c%s\n", IMAGETAG_CMDLINE_PACKAGE, c, (additional_error ? additional_error : ""));
+ abort ();
+ } /* switch */
+ } /* while */
+
+
+
+ if (check_required)
+ {
+ error += imagetag_cmdline_required2 (args_info, argv[0], additional_error);
+ }
+
+ imagetag_cmdline_release (&local_args_info);
+
+ if ( error )
+ return (EXIT_FAILURE);
+
+ return 0;
+
+failure:
+
+ imagetag_cmdline_release (&local_args_info);
+ return (EXIT_FAILURE);
+}
diff --git a/tools/firmware-utils/src/imagetag_cmdline.h b/tools/firmware-utils/src/imagetag_cmdline.h
new file mode 100644
index 0000000..3f55c50
--- /dev/null
+++ b/tools/firmware-utils/src/imagetag_cmdline.h
@@ -0,0 +1,275 @@
+/** @file imagetag_cmdline.h
+ * @brief The header file for the command line option parser
+ * generated by GNU Gengetopt version 2.22.5
+ * http://www.gnu.org/software/gengetopt.
+ * DO NOT modify this file, since it can be overwritten
+ * @author GNU Gengetopt by Lorenzo Bettini */
+
+#ifndef IMAGETAG_CMDLINE_H
+#define IMAGETAG_CMDLINE_H
+
+/* If we use autoconf. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h> /* for FILE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef IMAGETAG_CMDLINE_PACKAGE
+/** @brief the program name (used for printing errors) */
+#define IMAGETAG_CMDLINE_PACKAGE "imagetag"
+#endif
+
+#ifndef IMAGETAG_CMDLINE_PACKAGE_NAME
+/** @brief the complete program name (used for help and version) */
+#define IMAGETAG_CMDLINE_PACKAGE_NAME "imagetag"
+#endif
+
+#ifndef IMAGETAG_CMDLINE_VERSION
+/** @brief the program version */
+#define IMAGETAG_CMDLINE_VERSION "2.0.0"
+#endif
+
+/** @brief Where the command line options are stored */
+struct gengetopt_args_info
+{
+ const char *help_help; /**< @brief Print help and exit help description. */
+ const char *version_help; /**< @brief Print version and exit help description. */
+ char * kernel_arg; /**< @brief File with LZMA compressed kernel to include in the image.. */
+ char * kernel_orig; /**< @brief File with LZMA compressed kernel to include in the image. original value given at command line. */
+ const char *kernel_help; /**< @brief File with LZMA compressed kernel to include in the image. help description. */
+ char * rootfs_arg; /**< @brief File with RootFS to include in the image.. */
+ char * rootfs_orig; /**< @brief File with RootFS to include in the image. original value given at command line. */
+ const char *rootfs_help; /**< @brief File with RootFS to include in the image. help description. */
+ char * output_arg; /**< @brief Name of output file.. */
+ char * output_orig; /**< @brief Name of output file. original value given at command line. */
+ const char *output_help; /**< @brief Name of output file. help description. */
+ char * cfe_arg; /**< @brief File with CFE to include in the image.. */
+ char * cfe_orig; /**< @brief File with CFE to include in the image. original value given at command line. */
+ const char *cfe_help; /**< @brief File with CFE to include in the image. help description. */
+ char * boardid_arg; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\").. */
+ char * boardid_orig; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\"). original value given at command line. */
+ const char *boardid_help; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\"). help description. */
+ char * chipid_arg; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\").. */
+ char * chipid_orig; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\"). original value given at command line. */
+ const char *chipid_help; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\"). help description. */
+ char * flash_start_arg; /**< @brief Flash start address. (default='0xBFC00000'). */
+ char * flash_start_orig; /**< @brief Flash start address. original value given at command line. */
+ const char *flash_start_help; /**< @brief Flash start address. help description. */
+ char * image_offset_arg; /**< @brief Offset from start address for the first byte after the CFE (in memory). (default='0x10000'). */
+ char * image_offset_orig; /**< @brief Offset from start address for the first byte after the CFE (in memory). original value given at command line. */
+ const char *image_offset_help; /**< @brief Offset from start address for the first byte after the CFE (in memory). help description. */
+ char * tag_version_arg; /**< @brief Version number for imagetag format. (default='6'). */
+ char * tag_version_orig; /**< @brief Version number for imagetag format. original value given at command line. */
+ const char *tag_version_help; /**< @brief Version number for imagetag format. help description. */
+ char * signature_arg; /**< @brief Magic string (signature), for boards that need it. (default='Broadcom Corporatio'). */
+ char * signature_orig; /**< @brief Magic string (signature), for boards that need it. original value given at command line. */
+ const char *signature_help; /**< @brief Magic string (signature), for boards that need it. help description. */
+ char * signature2_arg; /**< @brief Second magic string (signature2). (default='ver. 2.0'). */
+ char * signature2_orig; /**< @brief Second magic string (signature2). original value given at command line. */
+ const char *signature2_help; /**< @brief Second magic string (signature2). help description. */
+ char * block_size_arg; /**< @brief Flash erase block size. (default='0x10000'). */
+ char * block_size_orig; /**< @brief Flash erase block size. original value given at command line. */
+ const char *block_size_help; /**< @brief Flash erase block size. help description. */
+ char * load_addr_arg; /**< @brief Kernel load address.. */
+ char * load_addr_orig; /**< @brief Kernel load address. original value given at command line. */
+ const char *load_addr_help; /**< @brief Kernel load address. help description. */
+ char * entry_arg; /**< @brief Address where the kernel entry point will be for booting.. */
+ char * entry_orig; /**< @brief Address where the kernel entry point will be for booting. original value given at command line. */
+ const char *entry_help; /**< @brief Address where the kernel entry point will be for booting. help description. */
+ char * layoutver_arg; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this).. */
+ char * layoutver_orig; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this). original value given at command line. */
+ const char *layoutver_help; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this). help description. */
+ char * info1_arg; /**< @brief String for first vendor information section.. */
+ char * info1_orig; /**< @brief String for first vendor information section. original value given at command line. */
+ const char *info1_help; /**< @brief String for first vendor information section. help description. */
+ char * altinfo_arg; /**< @brief String for vendor information section (alternate/pirelli).. */
+ char * altinfo_orig; /**< @brief String for vendor information section (alternate/pirelli). original value given at command line. */
+ const char *altinfo_help; /**< @brief String for vendor information section (alternate/pirelli). help description. */
+ char * info2_arg; /**< @brief String for second vendor information section.. */
+ char * info2_orig; /**< @brief String for second vendor information section. original value given at command line. */
+ const char *info2_help; /**< @brief String for second vendor information section. help description. */
+ int root_first_flag; /**< @brief Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory). (default=off). */
+ const char *root_first_help; /**< @brief Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory). help description. */
+ char * rsa_signature_arg; /**< @brief String for RSA Signature section.. */
+ char * rsa_signature_orig; /**< @brief String for RSA Signature section. original value given at command line. */
+ const char *rsa_signature_help; /**< @brief String for RSA Signature section. help description. */
+ char * second_image_flag_arg; /**< @brief Dual Image Flag (2=not-specified). (default='2'). */
+ char * second_image_flag_orig; /**< @brief Dual Image Flag (2=not-specified). original value given at command line. */
+ const char *second_image_flag_help; /**< @brief Dual Image Flag (2=not-specified). help description. */
+ char * inactive_arg; /**< @brief Inactive Flag (2=not-specified). (default='2'). */
+ char * inactive_orig; /**< @brief Inactive Flag (2=not-specified). original value given at command line. */
+ const char *inactive_help; /**< @brief Inactive Flag (2=not-specified). help description. */
+ char * reserved2_arg; /**< @brief String for second reserved section.. */
+ char * reserved2_orig; /**< @brief String for second reserved section. original value given at command line. */
+ const char *reserved2_help; /**< @brief String for second reserved section. help description. */
+ int kernel_file_has_header_flag; /**< @brief Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed (default=off). */
+ const char *kernel_file_has_header_help; /**< @brief Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed help description. */
+ int pad_arg; /**< @brief Pad the image to this size if smaller (in MiB). */
+ char * pad_orig; /**< @brief Pad the image to this size if smaller (in MiB) original value given at command line. */
+ const char *pad_help; /**< @brief Pad the image to this size if smaller (in MiB) help description. */
+ int align_rootfs_flag; /**< @brief Align the rootfs start to erase block size (default=off). */
+ const char *align_rootfs_help; /**< @brief Align the rootfs start to erase block size help description. */
+
+ unsigned int help_given ; /**< @brief Whether help was given. */
+ unsigned int version_given ; /**< @brief Whether version was given. */
+ unsigned int kernel_given ; /**< @brief Whether kernel was given. */
+ unsigned int rootfs_given ; /**< @brief Whether rootfs was given. */
+ unsigned int output_given ; /**< @brief Whether output was given. */
+ unsigned int cfe_given ; /**< @brief Whether cfe was given. */
+ unsigned int boardid_given ; /**< @brief Whether boardid was given. */
+ unsigned int chipid_given ; /**< @brief Whether chipid was given. */
+ unsigned int flash_start_given ; /**< @brief Whether flash-start was given. */
+ unsigned int image_offset_given ; /**< @brief Whether image-offset was given. */
+ unsigned int tag_version_given ; /**< @brief Whether tag-version was given. */
+ unsigned int signature_given ; /**< @brief Whether signature was given. */
+ unsigned int signature2_given ; /**< @brief Whether signature2 was given. */
+ unsigned int block_size_given ; /**< @brief Whether block-size was given. */
+ unsigned int load_addr_given ; /**< @brief Whether load-addr was given. */
+ unsigned int entry_given ; /**< @brief Whether entry was given. */
+ unsigned int layoutver_given ; /**< @brief Whether layoutver was given. */
+ unsigned int info1_given ; /**< @brief Whether info1 was given. */
+ unsigned int altinfo_given ; /**< @brief Whether altinfo was given. */
+ unsigned int info2_given ; /**< @brief Whether info2 was given. */
+ unsigned int root_first_given ; /**< @brief Whether root-first was given. */
+ unsigned int rsa_signature_given ; /**< @brief Whether rsa-signature was given. */
+ unsigned int second_image_flag_given ; /**< @brief Whether second-image-flag was given. */
+ unsigned int inactive_given ; /**< @brief Whether inactive was given. */
+ unsigned int reserved2_given ; /**< @brief Whether reserved2 was given. */
+ unsigned int kernel_file_has_header_given ; /**< @brief Whether kernel-file-has-header was given. */
+ unsigned int pad_given ; /**< @brief Whether pad was given. */
+ unsigned int align_rootfs_given ; /**< @brief Whether align-rootfs was given. */
+
+} ;
+
+/** @brief The additional parameters to pass to parser functions */
+struct imagetag_cmdline_params
+{
+ int override; /**< @brief whether to override possibly already present options (default 0) */
+ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
+ int check_required; /**< @brief whether to check that all required options were provided (default 1) */
+ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
+ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
+} ;
+
+/** @brief the purpose string of the program */
+extern const char *gengetopt_args_info_purpose;
+/** @brief the usage string of the program */
+extern const char *gengetopt_args_info_usage;
+/** @brief all the lines making the help output */
+extern const char *gengetopt_args_info_help[];
+
+/**
+ * The command line parser
+ * @param argc the number of command line options
+ * @param argv the command line options
+ * @param args_info the structure where option information will be stored
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int imagetag_cmdline (int argc, char **argv,
+ struct gengetopt_args_info *args_info);
+
+/**
+ * The command line parser (version with additional parameters - deprecated)
+ * @param argc the number of command line options
+ * @param argv the command line options
+ * @param args_info the structure where option information will be stored
+ * @param override whether to override possibly already present options
+ * @param initialize whether to initialize the option structure my_args_info
+ * @param check_required whether to check that all required options were provided
+ * @return 0 if everything went fine, NON 0 if an error took place
+ * @deprecated use imagetag_cmdline_ext() instead
+ */
+int imagetag_cmdline2 (int argc, char **argv,
+ struct gengetopt_args_info *args_info,
+ int override, int initialize, int check_required);
+
+/**
+ * The command line parser (version with additional parameters)
+ * @param argc the number of command line options
+ * @param argv the command line options
+ * @param args_info the structure where option information will be stored
+ * @param params additional parameters for the parser
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int imagetag_cmdline_ext (int argc, char **argv,
+ struct gengetopt_args_info *args_info,
+ struct imagetag_cmdline_params *params);
+
+/**
+ * Save the contents of the option struct into an already open FILE stream.
+ * @param outfile the stream where to dump options
+ * @param args_info the option struct to dump
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int imagetag_cmdline_dump(FILE *outfile,
+ struct gengetopt_args_info *args_info);
+
+/**
+ * Save the contents of the option struct into a (text) file.
+ * This file can be read by the config file parser (if generated by gengetopt)
+ * @param filename the file where to save
+ * @param args_info the option struct to save
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int imagetag_cmdline_file_save(const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/**
+ * Print the help
+ */
+void imagetag_cmdline_print_help(void);
+/**
+ * Print the version
+ */
+void imagetag_cmdline_print_version(void);
+
+/**
+ * Initializes all the fields a imagetag_cmdline_params structure
+ * to their default values
+ * @param params the structure to initialize
+ */
+void imagetag_cmdline_params_init(struct imagetag_cmdline_params *params);
+
+/**
+ * Allocates dynamically a imagetag_cmdline_params structure and initializes
+ * all its fields to their default values
+ * @return the created and initialized imagetag_cmdline_params structure
+ */
+struct imagetag_cmdline_params *imagetag_cmdline_params_create(void);
+
+/**
+ * Initializes the passed gengetopt_args_info structure's fields
+ * (also set default values for options that have a default)
+ * @param args_info the structure to initialize
+ */
+void imagetag_cmdline_init (struct gengetopt_args_info *args_info);
+/**
+ * Deallocates the string fields of the gengetopt_args_info structure
+ * (but does not deallocate the structure itself)
+ * @param args_info the structure to deallocate
+ */
+void imagetag_cmdline_free (struct gengetopt_args_info *args_info);
+
+/**
+ * Checks that all the required options were specified
+ * @param args_info the structure to check
+ * @param prog_name the name of the program that will be used to print
+ * possible errors
+ * @return
+ */
+int imagetag_cmdline_required (struct gengetopt_args_info *args_info,
+ const char *prog_name);
+
+extern const char *imagetag_cmdline_second_image_flag_values[]; /**< @brief Possible values for second-image-flag. */
+extern const char *imagetag_cmdline_inactive_values[]; /**< @brief Possible values for inactive. */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* IMAGETAG_CMDLINE_H */
diff --git a/tools/firmware-utils/src/lzma2eva.c b/tools/firmware-utils/src/lzma2eva.c
new file mode 100644
index 0000000..0bc13fa
--- /dev/null
+++ b/tools/firmware-utils/src/lzma2eva.c
@@ -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;
+}
diff --git a/tools/firmware-utils/src/makeamitbin.c b/tools/firmware-utils/src/makeamitbin.c
new file mode 100644
index 0000000..5c33442
--- /dev/null
+++ b/tools/firmware-utils/src/makeamitbin.c
@@ -0,0 +1,316 @@
+/*
+ * makeamitbin - create firmware binaries for MGB100
+ *
+ * Copyright (C) 2007 Volker Weiss <dev@tintuc.de>
+ * Christian Welzel <dev@welzel-online.ch>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* defaults: Level One WAP-0007 */
+static char *ascii1 = "DDC_RUS001";
+static char *ascii2 = "Queen";
+
+static struct hdrinfo {
+ char *name;
+ unsigned long unknown; /* can probably be any number, maybe version number */
+ int topalign;
+ unsigned int addr;
+ unsigned int size;
+} hdrinfo[] = {
+ { "bios", 0xc76be111, 1, 0x3fa000, 0x006000 }, /* BIOS */
+ { "recovery", 0xc76be222, 0, 0x3f0000, 0x004000 }, /* Recovery Loader */
+ { "linux", 0xc76bee9d, 0, 0x000000, 0x100000 }, /* Linux */
+ { "ramdisk", 0xc76bee9d, 0, 0x100000, 0x280000 }, /* ramdisk */
+ { "amitconfig", 0xc76bee8b, 0, 0x380000, 0x060000 }, /* AMIT config */
+ { "redboot", 0x00000000, 1, 0x3d0000, 0x030000 }, /* Redboot 128kB image */
+ { "redbootlow", 0, 0, 0x3e0000, 0x18000 }, /* Redboot 1. part */
+ { "redboothigh", 0, 0, 0x3fa000, 0x6000 }, /* Redboot 2. part */
+ { "linux3g", 0xcb5f06b5, 0, 0x000000, 0x100000 }, /* Linux */
+ { "ramdisk3g", 0xcb5f06b5, 0, 0x100000, 0x280000 }, /* ramdisk */
+ { NULL }
+};
+
+/*
+CHD2WLANU_R400b7
+
+11e1 6bc7
+22e2 6bc7
+5dc3 47c8
+5cc3 47c8
+21c3 47c8
+*/
+
+/*
+20060106_DDC_WAP-0007_R400b4
+
+11e1 6bc7
+22e2 6bc7
+9dee 6bc7
+9dee 6bc7
+8bee 6bc7
+*/
+
+/*
+WMU-6000FS_R400b6
+
+11e1 6bc7
+22e2 6bc7
+6d2d 0fc8
+6c2d 0fc8
+542d 0fc8
+*/
+
+/*
+WAP-0007(R4.00b8)_2006-10-02
+
+9979 5fc8
+22e2 6bc7
+c46e cec8
+c36e cec8
+a76e cec8
+*/
+
+
+
+#define HDRSIZE 80
+
+#define COPY_SHORT(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \
+ d[o+1] = (unsigned char)(((v) >> 8) & 0xff)
+#define COPY_LONG(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \
+ d[o+1] = (unsigned char)(((v) >> 8) & 0xff); \
+ d[o+2] = (unsigned char)(((v) >> 16) & 0xff); \
+ d[o+3] = (unsigned char)(((v) >> 24) & 0xff)
+#define READ_SHORT(d, o) ((unsigned short)(d[o+0]) + \
+ (((unsigned short)(d[o+1])) << 8))
+
+/*
+00..0d ASCII product ID
+0e..0f checksum of payload
+10..1b ASCII Queen
+1c..1f AMIT BIOS: 11e1 6bc7, Recovery Tool: 22e2 6bc7
+ Linux: 5dc3 47c8, ramdisk: 5cc3 47c8
+ AMIT FS: 21c3 47c8 VERSION NUMBER??????
+20..23 offset in flash aligned to segment boundary
+24..27 length in flash aligned to segment boundary
+28..2b offset in flash (payload)
+2c..2f length (payload)
+30..3f always 0
+40..47 always 4248 0101 5000 0001 (last maybe .....0501)
+48..4b same as 20..23
+4c..4d always 0b00
+4e..4f inverted checksum of header
+*/
+
+unsigned short checksum(unsigned char *data, long size)
+{
+ long n;
+ unsigned short d, cs = 0;
+ for (n = 0; n < size; n += 2)
+ {
+ d = READ_SHORT(data, n);
+ cs += d;
+ if (cs < d)
+ cs++;
+ }
+ if (size & 1)
+ {
+ d = data[n];
+ cs += d;
+ if (cs < d)
+ cs++;
+ }
+ return cs;
+}
+
+void showhdr(unsigned char *hdr)
+{
+ int i, j;
+ for (j = 0; j < 5; j++)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ printf("%02x ", (unsigned int)(hdr[j * 16 + i]));
+ }
+ printf(" ");
+ for (i = 0; i < 16; i++)
+ {
+ unsigned char d = hdr[j * 16 + i];
+ printf("%c", (d >= ' ' && d < 127) ? d : '.');
+ }
+ printf("\n");
+ }
+}
+
+void makehdr(unsigned char *hdr, struct hdrinfo *info,
+ unsigned char *data, long size, int last)
+{
+ unsigned int offset = info->addr + 0x10;
+ memset(hdr, 0, HDRSIZE);
+ if (info->topalign)
+ offset = info->addr + info->size - size; /* top align */
+ strncpy((char *)hdr + 0x00, ascii1, 14);
+ strncpy((char *)hdr + 0x10, ascii2, 12);
+ COPY_LONG(hdr, 0x1c, info->unknown);
+ COPY_LONG(hdr, 0x20, info->addr);
+ COPY_LONG(hdr, 0x24, info->size);
+ COPY_LONG(hdr, 0x28, offset);
+ COPY_LONG(hdr, 0x2c, size);
+ COPY_LONG(hdr, 0x40, 0x01014842);
+ COPY_LONG(hdr, 0x44, last ? 0x01050050 : 0x01000050);
+ COPY_LONG(hdr, 0x48, info->addr);
+ COPY_SHORT(hdr, 0x4c, info->unknown == 0xcb5f06b5 ? 0x0016 : 0x000b);
+ COPY_SHORT(hdr, 0x0e, checksum(data, size));
+ COPY_SHORT(hdr, 0x4e, ~checksum(hdr, HDRSIZE));
+}
+
+unsigned char *read_file(const char *name, long *size)
+{
+ FILE *f;
+ unsigned char *data = NULL;
+ *size = 0;
+ f = fopen(name, "r");
+ if (f != NULL)
+ {
+ if (fseek(f, 0, SEEK_END) == 0)
+ {
+ *size = ftell(f);
+ if (*size != -1)
+ {
+ if (fseek(f, 0, SEEK_SET) == 0)
+ {
+ data = (unsigned char *)malloc(*size);
+ if (data != NULL)
+ {
+ if (fread(data, sizeof(char), *size, f) != *size)
+ {
+ free(data);
+ data = NULL;
+ }
+ }
+ }
+ }
+ }
+ fclose(f);
+ }
+ return data;
+}
+
+struct hdrinfo *find_hdrinfo(const char *name)
+{
+ int n;
+ for (n = 0; hdrinfo[n].name != NULL; n++)
+ {
+ if (strcmp(name, hdrinfo[n].name) == 0)
+ return &hdrinfo[n];
+ }
+ return NULL;
+}
+
+void oferror(FILE *f)
+{
+ printf("file error\n");
+ exit(2);
+}
+
+void showhelp(void)
+{
+ printf("Syntax: makeamitbin [options]\n");
+ printf("Options:\n");
+ printf(" -1 ID1\tFirmware identifier 1, e.g. 'DDC_RUS001' for manufacturer LevelOne\n");
+ printf(" -2 ID2\tFirmware identifier 2, 'Queen' in all known cases\n");
+ printf(" -o FILE\tOutput file\n");
+ printf(" -ids\t\tShow a list of known firmware identifiers.\n");
+ exit(1);
+}
+
+void show_fwids(void)
+{
+ printf("List of known firmware identifiers:\n");
+ printf("Manufacturer\t\tProduct\t\tIdentifier\n");
+ printf("=====================================================\n");
+ printf("Conceptronic\t\tCHD2WLANU\tLLM_RUS001\n");
+ printf("Pearl\t\t\tPE6643\t\tQueen\n");
+ printf("Micronica\t\tMGB100\t\tQueen\n");
+ printf("LevelOne\t\tWAP-0007\tDDC_RUS001\n");
+ printf("SMC\t\t\tWAPS-G\t\tSMC_RUS001\n");
+ printf("OvisLink (AirLive)\tWMU-6\t\tOVS_RUS001\n");
+ printf("SafeCom SWSAPUR-5\tFMW\t\tSafeco_RPS001\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned char hdr[HDRSIZE];
+ unsigned char *data;
+ FILE *of;
+ char *outfile = NULL;
+ char *type;
+ struct hdrinfo *info;
+ long size;
+ int last = 0;
+ int n;
+ for (n = 1; n < argc; n++)
+ {
+ if (strcmp(argv[n], "-1") == 0)
+ ascii1 = argv[n+1];
+ if (strcmp(argv[n], "-2") == 0)
+ ascii2 = argv[n+1];
+ if (strcmp(argv[n], "-o") == 0)
+ outfile = argv[n+1];
+ if (strcmp(argv[n], "-ids") == 0)
+ show_fwids();
+ }
+ if (ascii1 == NULL || ascii2 == NULL || outfile == NULL)
+ showhelp();
+ of = fopen(outfile, "w");
+ if (of == NULL)
+ oferror(of);
+ for (n = 1; n < argc; n++)
+ {
+ if (strncmp(argv[n], "-", 1) != 0)
+ {
+ type = argv[n++];
+ if (n >= argc)
+ showhelp();
+ last = ((n + 1) >= argc); /* dirty, options first! */
+ info = find_hdrinfo(type);
+ if (info == NULL)
+ showhelp();
+ data = read_file(argv[n], &size);
+ if (data == NULL)
+ showhelp();
+ makehdr(hdr, info, data, size, last);
+ /* showhdr(hdr); */
+ if (fwrite(hdr, HDRSIZE, 1, of) != 1)
+ oferror(of);
+ if (fwrite(data, size, 1, of) != 1)
+ oferror(of);
+ free(data);
+ }
+ else
+ n++;
+ }
+ if (fclose(of) != 0)
+ oferror(NULL);
+ return 0;
+}
diff --git a/tools/firmware-utils/src/md5.c b/tools/firmware-utils/src/md5.c
new file mode 100644
index 0000000..2039760
--- /dev/null
+++ b/tools/firmware-utils/src/md5.c
@@ -0,0 +1,307 @@
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#include <string.h>
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ ** Message-digest routines: **
+ ** To form the message digest for a message M **
+ ** (1) Initialize a context buffer mdContext using MD5_Init **
+ ** (2) Call MD5_Update on mdContext and M **
+ ** (3) Call MD5_Final on mdContext **
+ ** The message digest is now in mdContext->digest[0...15] **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform ();
+
+static unsigned char PADDING[64] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) \
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) \
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) \
+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#ifdef __STDC__
+#define UL(x) x##U
+#else
+#define UL(x) x
+#endif
+
+/* The routine MD5_Init initializes the message-digest context
+ mdContext. All fields are set to zero.
+ */
+void MD5_Init (mdContext)
+MD5_CTX *mdContext;
+{
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+ /* Load magic initialization constants.
+ */
+ mdContext->buf[0] = (UINT4)0x67452301;
+ mdContext->buf[1] = (UINT4)0xefcdab89;
+ mdContext->buf[2] = (UINT4)0x98badcfe;
+ mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+ account for the presence of each of the characters inBuf[0..inLen-1]
+ in the message whose digest is being computed.
+ */
+void MD5_Update (mdContext, inBuf, inLen)
+MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* update number of bits */
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+ mdContext->i[1]++;
+ mdContext->i[0] += ((UINT4)inLen << 3);
+ mdContext->i[1] += ((UINT4)inLen >> 29);
+
+ while (inLen--) {
+ /* add new character to buffer, increment mdi */
+ mdContext->in[mdi++] = *inBuf++;
+
+ /* transform if necessary */
+ if (mdi == 0x40) {
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+ mdi = 0;
+ }
+ }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+ ends with the desired message digest in mdContext->digest[0...15].
+ */
+void MD5_Final (hash, mdContext)
+unsigned char hash[];
+MD5_CTX *mdContext;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+ unsigned int padLen;
+
+ /* save number of bits */
+ in[14] = mdContext->i[0];
+ in[15] = mdContext->i[1];
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* pad out to 56 mod 64 */
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ MD5_Update (mdContext, PADDING, padLen);
+
+ /* append length in bits and transform */
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+
+ /* store buffer in digest */
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+ mdContext->digest[ii+1] =
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+ mdContext->digest[ii+2] =
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+ mdContext->digest[ii+3] =
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+ }
+ memcpy(hash, mdContext->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
+ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
+ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c **
+ ******************************** (cut) ********************************
+ */
diff --git a/tools/firmware-utils/src/md5.h b/tools/firmware-utils/src/md5.h
new file mode 100644
index 0000000..f7a0c96
--- /dev/null
+++ b/tools/firmware-utils/src/md5.h
@@ -0,0 +1,65 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5 **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ ** Revised (for MD5): RLR 4/27/91 **
+ ** -- G modified to have y&~z instead of y&z **
+ ** -- FF, GG, HH modified to add in last register done **
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
+ ** -- distinct additive constant for each step **
+ ** -- round 4 added, working mod 7 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+/* typedef a 32-bit type */
+#ifdef _LP64
+typedef unsigned int UINT4;
+typedef int INT4;
+#else
+typedef unsigned long UINT4;
+typedef long INT4;
+#endif
+#define _UINT4_T
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after MD5Final call */
+} MD5_CTX;
+
+void MD5_Init ();
+void MD5_Update ();
+void MD5_Final ();
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */
diff --git a/tools/firmware-utils/src/mkbrncmdline.c b/tools/firmware-utils/src/mkbrncmdline.c
new file mode 100644
index 0000000..6eb4bfe
--- /dev/null
+++ b/tools/firmware-utils/src/mkbrncmdline.c
@@ -0,0 +1,168 @@
+/*
+ * mkbrncmdline.c - partially based on OpenWrt's wndr3700.c
+ *
+ * Copyright (C) 2011 Tobias Diedrich <ranma+openwrt@tdiedrich.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+static void usage(const char *) __attribute__ (( __noreturn__ ));
+
+static void usage(const char *mess)
+{
+ fprintf(stderr, "Error: %s\n", mess);
+ fprintf(stderr, "Usage: mkbrncmdline -i input_file -o output_file [-a loadaddress] arg1 [argx ...]\n");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static char *input_file = NULL;
+static char *output_file = NULL;
+static unsigned loadaddr = 0x80002000;
+
+static void parseopts(int *argc, char ***argv)
+{
+ char *endptr;
+ int res;
+
+ while ((res = getopt(*argc, *argv, "a:i:o:")) != -1) {
+ switch (res) {
+ default:
+ usage("Unknown option");
+ break;
+ case 'a':
+ loadaddr = strtoul(optarg, &endptr, 0);
+ if (endptr == optarg || *endptr != 0)
+ usage("loadaddress must be a decimal or hexadecimal 32-bit value");
+ break;
+ case 'i':
+ input_file = optarg;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ }
+ }
+ *argc -= optind;
+ *argv += optind;
+}
+
+static void emitload(int outfd, int reg, unsigned value)
+{
+ char buf[8] = {
+ 0x3c, 0x04 + reg,
+ value >> 24, value >> 16,
+ 0x34, 0x84 + reg + (reg << 5),
+ value >> 8, value,
+ };
+ if (write(outfd, buf, sizeof(buf)) != sizeof(buf)) {
+ fprintf(stderr, "write: %s\n", strerror(errno));
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int outfd;
+ int i;
+ int fd;
+ size_t len, skip, buf_len;
+ unsigned cmdline_addr;
+ unsigned s_ofs;
+ char *buf;
+
+ parseopts(&argc, &argv);
+
+ if (argc < 1)
+ usage("must specify at least one kernel cmdline argument");
+
+ if (input_file == NULL || output_file == NULL)
+ usage("must specify input and output file");
+
+ if ((outfd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
+ {
+ fprintf(stderr, "Error opening '%s' for writing: %s\n", output_file, strerror(errno));
+ exit(1);
+ }
+
+ // mmap input_file
+ if ((fd = open(input_file, O_RDONLY)) < 0
+ || (len = lseek(fd, 0, SEEK_END)) < 0
+ || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1)
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error mapping file '%s': %s\n", input_file, strerror(errno));
+ exit(1);
+ }
+
+ cmdline_addr = loadaddr + len;
+
+ // Kernel args are passed in registers a0,a1,a2 and a3
+ emitload(outfd, 0, 0); /* a0 = 0 */
+ emitload(outfd, 1, 0); /* a1 = 0 */
+ emitload(outfd, 2, cmdline_addr); /* a2 = &cmdline */
+ emitload(outfd, 3, 0); /* a3 = 0 */
+ skip = lseek(outfd, 0, SEEK_END);
+
+ // write the kernel
+ if (write(outfd, input_file + skip, len - skip) != len -skip) {
+ fprintf(stderr, "write: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ // write cmdline structure
+ buf_len = (argc + 1) * 4;
+ for (i=0; i<argc; i++) {
+ buf_len += strlen(argv[i]) + 1;
+ }
+ buf = malloc(buf_len + 16);
+ if (!buf) {
+ fprintf(stderr, "Could not allocate memory for cmdline buffer\n");
+ exit(1);
+ }
+ memset(buf, 0, buf_len);
+
+ s_ofs = 4 * (argc + 1);
+ for (i=0; i<argc; i++) {
+ unsigned s_ptr = cmdline_addr + s_ofs;
+ buf[i * 4 + 0] = s_ptr >> 24;
+ buf[i * 4 + 1] = s_ptr >> 16;
+ buf[i * 4 + 2] = s_ptr >> 8;
+ buf[i * 4 + 3] = s_ptr >> 0;
+ memcpy(&buf[s_ofs], argv[i], strlen(argv[i]));
+ s_ofs += strlen(argv[i]) + 1;
+ }
+ if (write(outfd, buf, buf_len) != buf_len) {
+ fprintf(stderr, "write: %s\n", strerror(errno));
+ exit(1);
+ }
+
+
+ munmap(input_file, len);
+ close(outfd);
+ free(buf);
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/mkbrnimg.c b/tools/firmware-utils/src/mkbrnimg.c
new file mode 100644
index 0000000..b7a73ff
--- /dev/null
+++ b/tools/firmware-utils/src/mkbrnimg.c
@@ -0,0 +1,189 @@
+/*
+ * mkbrnimg.c - partially based on OpenWrt's wndr3700.c
+ *
+ * Copyright (C) 2011 Tobias Diedrich <ranma+openwrt@tdiedrich.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#define BPB 8 /* bits/byte */
+
+static uint32_t crc32[1<<BPB];
+
+static char *output_file = "default-brnImage";
+static uint32_t magic = 0x12345678;
+static char *signature = "BRNDTW502";
+static uint32_t crc32_poly = 0x2083b8ed;
+
+static void init_crc32()
+{
+ const uint32_t poly = ntohl(crc32_poly);
+ int n;
+
+ for (n = 0; n < 1<<BPB; n++) {
+ uint32_t crc = n;
+ int bit;
+
+ for (bit = 0; bit < BPB; bit++)
+ crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
+ crc32[n] = crc;
+ }
+}
+
+static uint32_t crc32buf(unsigned char *buf, size_t len)
+{
+ uint32_t crc = 0xFFFFFFFF;
+
+ for (; len; len--, buf++)
+ crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB);
+ return ~crc;
+}
+
+static void usage(const char *) __attribute__ (( __noreturn__ ));
+
+static void usage(const char *mess)
+{
+ fprintf(stderr, "Error: %s\n", mess);
+ fprintf(stderr, "Usage: mkbrnimg [-o output_file] [-m magic] [-s signature] [-p crc32 poly] kernel_file [additional files]\n");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void parseopts(int *argc, char ***argv)
+{
+ char *endptr;
+ int res;
+
+ while ((res = getopt(*argc, *argv, "o:m:s:p:")) != -1) {
+ switch (res) {
+ default:
+ usage("Unknown option");
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ case 'm':
+ magic = strtoul(optarg, &endptr, 0);
+ if (endptr == optarg || *endptr != 0)
+ usage("magic must be a decimal or hexadecimal 32-bit value");
+ break;
+ case 's':
+ signature = optarg;
+ break;
+ case 'p':
+ crc32_poly = strtoul(optarg, &endptr, 0);
+ if (endptr == optarg || *endptr != 0)
+ usage("'crc32 poly' must be a decimal or hexadecimal 32-bit value");
+ break;
+ }
+ }
+ *argc -= optind;
+ *argv += optind;
+}
+
+static void appendfile(int outfd, char *path, int kernel) {
+ int fd;
+ size_t len, padded_len;
+ char *input_file;
+ uint32_t crc;
+ char padding[0x400];
+ char footer[12];
+
+ memset(padding, 0xff, sizeof(padding));
+
+ // mmap input_file
+ if ((fd = open(path, O_RDONLY)) < 0
+ || (len = lseek(fd, 0, SEEK_END)) < 0
+ || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1)
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error mapping file '%s': %s\n", path, strerror(errno));
+ exit(1);
+ }
+
+ // kernel should be lzma compressed image, not uImage
+ if (kernel &&
+ (input_file[0] != (char)0x5d ||
+ input_file[1] != (char)0x00 ||
+ input_file[2] != (char)0x00 ||
+ input_file[3] != (char)0x80)) {
+ fprintf(stderr, "lzma signature not found on kernel image.\n");
+ exit(1);
+ }
+
+ init_crc32();
+ crc = crc32buf(input_file, len);
+ fprintf(stderr, "crc32 for '%s' is %08x.\n", path, crc);
+
+ // write the file
+ write(outfd, input_file, len);
+
+ // write padding
+ padded_len = ((len + sizeof(footer) + sizeof(padding) - 1) & ~(sizeof(padding) - 1)) - sizeof(footer);
+ fprintf(stderr, "len=%08zx padded_len=%08zx\n", len, padded_len);
+ write(outfd, padding, padded_len - len);
+
+ // write footer
+ footer[0] = (len >> 0) & 0xff;
+ footer[1] = (len >> 8) & 0xff;
+ footer[2] = (len >> 16) & 0xff;
+ footer[3] = (len >> 24) & 0xff;
+ footer[4] = (magic >> 0) & 0xff;
+ footer[5] = (magic >> 8) & 0xff;
+ footer[6] = (magic >> 16) & 0xff;
+ footer[7] = (magic >> 24) & 0xff;
+ footer[8] = (crc >> 0) & 0xff;
+ footer[9] = (crc >> 8) & 0xff;
+ footer[10] = (crc >> 16) & 0xff;
+ footer[11] = (crc >> 24) & 0xff;
+ write(outfd, footer, sizeof(footer));
+
+ munmap(input_file, len);
+}
+
+int main(int argc, char **argv)
+{
+ int outfd;
+ int i;
+
+ parseopts(&argc, &argv);
+
+ if (argc < 1)
+ usage("wrong number of arguments");
+
+ if ((outfd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
+ {
+ fprintf(stderr, "Error opening '%s' for writing: %s\n", output_file, strerror(errno));
+ exit(1);
+ }
+
+ for (i=0; i<argc; i++) {
+ appendfile(outfd, argv[i], i == 0);
+ }
+ write(outfd, signature, strlen(signature)+1);
+ close(outfd);
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/mkcameofw.c b/tools/firmware-utils/src/mkcameofw.c
new file mode 100644
index 0000000..e0da4ba
--- /dev/null
+++ b/tools/firmware-utils/src/mkcameofw.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#define MAX_MODEL_LEN 20
+#define MAX_SIGNATURE_LEN 30
+#define MAX_REGION_LEN 4
+#define MAX_VERSION_LEN 12
+
+#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+struct file_info {
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+ uint32_t write_size;
+};
+
+struct img_header {
+ uint32_t checksum;
+ uint32_t image_size;
+ uint32_t kernel_size;
+ char model[MAX_MODEL_LEN];
+ char signature[MAX_SIGNATURE_LEN];
+ char region[MAX_REGION_LEN];
+ char version[MAX_VERSION_LEN];
+ unsigned char header_len;
+ unsigned char is_tgz;
+ unsigned char pad[4];
+} __attribute__ ((packed));
+
+/*
+ * Globals
+ */
+static char *ofname;
+static char *progname;
+
+static char *model;
+static char *signature;
+static char *region = "DEF";
+static char *version;
+static struct file_info kernel_info;
+static struct file_info rootfs_info;
+static uint32_t kernel_size;
+static uint32_t image_size;
+static int combined;
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -k <file> read kernel image from the file <file>\n"
+" -c use the kernel image as a combined image\n"
+" -M <model> set model to <model>\n"
+" -o <file> write output to the file <file>\n"
+" -r <file> read rootfs image from the file <file>\n"
+" -S <signature> set image signature to <signature>\n"
+" -R <region> set image region to <region>\n"
+" -V <version> set image version to <version>\n"
+" -I <size> set image size to <size>\n"
+" -K <size> set kernel size to <size>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+int
+str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+static int get_file_stat(struct file_info *fdata)
+{
+ struct stat st;
+ int res;
+
+ if (fdata->file_name == NULL)
+ return 0;
+
+ res = stat(fdata->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", fdata->file_name);
+ return res;
+ }
+
+ fdata->file_size = st.st_size;
+ fdata->write_size = fdata->file_size;
+ return 0;
+}
+
+static int read_to_buf(struct file_info *fdata, char *buf)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(fdata->file_name, "r");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", fdata->file_name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, fdata->file_size, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", fdata->file_name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+out_close:
+ fclose(f);
+out:
+ return ret;
+}
+
+static int check_options(void)
+{
+ int ret;
+
+#define CHKSTR(_name, _msg) \
+ do { \
+ if (_name == NULL) { \
+ ERR("no %s specified", _msg); \
+ return -1; \
+ } \
+ } while (0)
+
+#define CHKSTRLEN(_name, _msg) \
+ do { \
+ int field_len; \
+ CHKSTR(_name, _msg); \
+ field_len = FIELD_SIZEOF(struct img_header, _name) - 1; \
+ if (strlen(_name) > field_len) { \
+ ERR("%s is too long, max length is %d", \
+ _msg, field_len); \
+ return -1; \
+ } \
+ } while (0)
+
+ CHKSTRLEN(model, "model");
+ CHKSTRLEN(signature, "signature");
+ CHKSTRLEN(region, "region");
+ CHKSTRLEN(version, "version");
+ CHKSTR(ofname, "output file");
+ CHKSTR(kernel_info.file_name, "kernel image");
+
+ ret = get_file_stat(&kernel_info);
+ if (ret)
+ return ret;
+
+ if (combined) {
+ if (!kernel_size) {
+ ERR("kernel size must be specified for combined images");
+ return -1; \
+ }
+
+ if (!image_size)
+ image_size = kernel_info.file_size;
+
+ if (kernel_info.file_size > image_size) {
+ ERR("kernel image is too big");
+ return -1;
+ }
+
+ kernel_info.write_size = image_size;
+ } else {
+ CHKSTR(rootfs_info.file_name, "rootfs image");
+
+ ret = get_file_stat(&rootfs_info);
+ if (ret)
+ return ret;
+
+ if (kernel_size) {
+ /* override kernel size */
+ kernel_info.write_size = kernel_size;
+ }
+
+ if (image_size) {
+ if (image_size < kernel_info.write_size)
+ kernel_info.write_size = image_size;
+
+ /* override rootfs size */
+ rootfs_info.write_size = image_size - kernel_info.write_size;
+ }
+
+ if (kernel_info.file_size > kernel_info.write_size) {
+ ERR("kernel image is too big");
+ return -1;
+ }
+
+ if (rootfs_info.file_size > rootfs_info.write_size) {
+ ERR("rootfs image is too big");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int write_fw(char *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "w");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ DBG("firmware file \"%s\" completed", ofname);
+
+ ret = EXIT_SUCCESS;
+
+out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+out:
+ return ret;
+}
+
+static uint32_t get_csum(unsigned char *p, uint32_t len)
+{
+ uint32_t csum = 0;
+
+ while (len--)
+ csum += *p++;
+
+ return csum;
+}
+
+static int build_fw(void)
+{
+ int buflen;
+ char *buf;
+ char *p;
+ uint32_t csum;
+ struct img_header *hdr;
+ int ret = EXIT_FAILURE;
+
+ buflen = sizeof(struct img_header) +
+ kernel_info.write_size + rootfs_info.write_size;
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ memset(buf, 0, buflen);
+
+ p = buf + sizeof(struct img_header);
+
+ /* read kernel data */
+ ret = read_to_buf(&kernel_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ if (!combined) {
+ p += kernel_info.write_size;
+
+ /* read rootfs data */
+ ret = read_to_buf(&rootfs_info, p);
+ if (ret)
+ goto out_free_buf;
+ }
+
+ csum = get_csum((unsigned char *)(buf + sizeof(struct img_header)),
+ buflen - sizeof(struct img_header));
+
+ /* fill firmware header */
+ hdr = (struct img_header *) buf;
+
+ hdr->checksum = htonl(csum);
+ hdr->image_size = htonl(buflen - sizeof(struct img_header));
+ if (!combined)
+ hdr->kernel_size = htonl(kernel_info.write_size);
+ else
+ hdr->kernel_size = htonl(kernel_size);
+ hdr->header_len = sizeof(struct img_header);
+ strncpy(hdr->model, model, sizeof(hdr->model));
+ strncpy(hdr->signature, signature, sizeof(hdr->signature));
+ strncpy(hdr->version, version, sizeof(hdr->version));
+ strncpy(hdr->region, region, sizeof(hdr->region));
+
+ ret = write_fw(buf, buflen);
+ if (ret)
+ goto out_free_buf;
+
+ ret = EXIT_SUCCESS;
+
+out_free_buf:
+ free(buf);
+out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+
+ progname = basename(argv[0]);
+
+ while (1) {
+ int c;
+
+ c = getopt(argc, argv, "M:S:V:R:k:K:I:r:o:hc");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'M':
+ model = optarg;
+ break;
+ case 'S':
+ signature = optarg;
+ break;
+ case 'V':
+ version = optarg;
+ break;
+ case 'R':
+ region = optarg;
+ break;
+ case 'k':
+ kernel_info.file_name = optarg;
+ break;
+ case 'K':
+ if (str2u32(optarg, &kernel_size)) {
+ ERR("%s is invalid '%s'",
+ "kernel size", optarg);
+ goto out;
+ }
+ break;
+ case 'I':
+ if (str2u32(optarg, &image_size)) {
+ ERR("%s is invalid '%s'",
+ "image size", optarg);
+ goto out;
+ }
+ break;
+ case 'r':
+ rootfs_info.file_name = optarg;
+ break;
+ case 'c':
+ combined = 1;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret)
+ goto out;
+
+ ret = build_fw();
+
+out:
+ return ret;
+}
+
diff --git a/tools/firmware-utils/src/mkcasfw.c b/tools/firmware-utils/src/mkcasfw.c
new file mode 100644
index 0000000..5655bf1
--- /dev/null
+++ b/tools/firmware-utils/src/mkcasfw.c
@@ -0,0 +1,1030 @@
+/*
+ *
+ * Copyright (C) 2007 OpenWrt.org
+ * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <endian.h> /* for __BYTE_ORDER */
+#if defined(__CYGWIN__)
+# include <byteswap.h>
+#endif
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define HOST_TO_LE16(x) (x)
+# define HOST_TO_LE32(x) (x)
+# define LE16_TO_HOST(x) (x)
+# define LE32_TO_HOST(x) (x)
+#else
+# define HOST_TO_LE16(x) bswap_16(x)
+# define HOST_TO_LE32(x) bswap_32(x)
+# define LE16_TO_HOST(x) bswap_16(x)
+# define LE32_TO_HOST(x) bswap_32(x)
+#endif
+
+#define MAX_NUM_BLOCKS 2
+#define MAX_ARG_COUNT 32
+#define MAX_ARG_LEN 1024
+#define FILE_BUF_LEN (16*1024)
+#define DEFAULT_PADC 0xFF
+
+#define DEFAULT_BLOCK_ALIGN 0x10000U
+
+#define CSUM_TYPE_NONE 0
+#define CSUM_TYPE_8 1
+#define CSUM_TYPE_16 2
+#define CSUM_TYPE_32 3
+
+struct csum_state{
+ int size;
+ uint32_t val;
+ uint32_t tmp;
+ int odd;
+};
+
+struct image_desc {
+ int need_file;
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+
+ uint32_t csum;
+ uint32_t out_size;
+ uint8_t padc;
+};
+
+struct fwhdr_nfs {
+ uint32_t type;
+ uint32_t kernel_offs;
+ uint32_t kernel_size;
+ uint32_t fs_offs;
+ uint32_t fs_size;
+ uint32_t kernel_csum;
+ uint32_t fs_csum;
+ uint32_t id;
+} __attribute__ ((packed));
+
+struct fwhdr_cas {
+ uint32_t type;
+ uint32_t kernel_offs;
+ uint32_t kernel_size;
+ uint32_t id;
+ uint32_t kernel_csum;
+ uint32_t magic1;
+ uint32_t magic2;
+ uint32_t magic3;
+} __attribute__ ((packed));
+
+union file_hdr {
+ struct fwhdr_cas cas;
+ struct fwhdr_nfs nfs;
+};
+
+struct board_info {
+ char *model;
+ char *name;
+ int header_type;
+ uint32_t id;
+ uint32_t max_kernel_size;
+ uint32_t max_fs_size;
+};
+
+#define HEADER_TYPE_NFS 0
+#define HEADER_TYPE_CAS 1
+
+#define KERNEL_SIZE_CAS (61*64*1024)
+#define KERNEL_SIZE_NFS (52*64*1024)
+#define FS_SIZE_NFS (9*64*1024)
+
+#define CAS_MAGIC1 0x5241AA55
+#define CAS_MAGIC2 0x524F4741
+#define CAS_MAGIC3 0xD3F22D4E
+
+/* Cellvision/SparkLAN products */
+#define MODEL_CAS_630 0x01000000
+#define MODEL_CAS_630W 0x01000000
+#define MODEL_CAS_670 0x01000000
+#define MODEL_CAS_670W 0x01000000
+#define MODEL_NFS_101U 0x01000000
+#define MODEL_NFS_101WU 0x01000003
+#define MODEL_NFS_202U 0x01000001
+#define MODEL_NFS_202WU 0x01000002
+
+/* Corega products */
+#define MODEL_CG_NSADP 0x01000020 /* NFS-101U */
+#define MODEL_CG_NSADPCR 0x01000021 /* NFS-202U */
+
+/* D-Link products */
+#define MODEL_DCS_950 0x01010102 /* CAS-630 */
+#define MODEL_DCS_950G 0x01020102 /* CAS-630W */
+#define MODEL_DNS_120 0x01000030 /* NFS-101U */
+#define MODEL_DNS_G120 0x01000032 /* NFS-101WU */
+
+/* Digitus products */
+#define MODEL_DN_16021 MODEL_CAS_630
+#define MODEL_DN_16022 MODEL_CAS_630W
+#define MODEL_DN_16030 MODEL_CAS_670
+#define MODEL_DN_16031 MODEL_CAS_670W
+#define MODEL_DN_7013 MODEL_NFS_101U
+
+/* Lobos products */
+#define MODEL_LB_SS01TXU 0x00000000
+
+/* Neu-Fusion products */
+
+/* Ovislink products */
+#define MODEL_MU_5000FS 0x01000040 /* NFS-101U */
+#define MODEL_WL_5420CAM 0x020B0101 /* CAS-630W? */
+#define MODEL_WL_5460CAM 0x020B0001 /* CAS-670W */
+
+/* Repotec products */
+
+/* Sitecom products */
+#define MODEL_LN_350 /* unknown */
+#define MODEL_LN_403 0x01020402
+#define MODEL_WL_401 0x01010402
+
+/* Surecom products */
+#define MODEL_EP_4001_MM 0x01030A02 /* CAS-630 */
+#define MODEL_EP_4002_MM 0x01020A02 /* CAS-630W */
+#define MODEL_EP_4011_MM 0x01010A02 /* CAS-670 */
+#define MODEL_EP_4012_MM 0x01000A02 /* CAS-670W */
+#define MODEL_EP_9812_U /* unknown */
+
+/* Trendnet products */
+#define MODEL_TN_U100 0x01000081 /* NFS-101U */
+#define MODEL_TN_U200 0x01000082 /* NFS-202U */
+
+/*
+ * Globals
+ */
+char *progname;
+char *ofname;
+int verblevel;
+int keep_invalid_images;
+int invalid_causes_error = 1;
+union file_hdr header;
+
+struct image_desc kernel_image;
+struct image_desc fs_image;
+
+struct board_info *board = NULL;
+
+#define BOARD(m, n, i, ks, fs, h) { \
+ .model = (m), \
+ .name = (n), \
+ .id = (i), \
+ .max_kernel_size = (ks), \
+ .max_fs_size = (fs), \
+ .header_type = (h) \
+ }
+
+#define BOARD_CAS(m,n,i) \
+ BOARD(m, n, i, KERNEL_SIZE_CAS, 0, HEADER_TYPE_CAS)
+#define BOARD_NFS(m,n,i) \
+ BOARD(m, n, i, KERNEL_SIZE_NFS, FS_SIZE_NFS, HEADER_TYPE_NFS)
+
+static struct board_info boards[] = {
+ /* Cellvision/Sparklan products */
+ BOARD_CAS("CAS-630", "Cellvision CAS-630", MODEL_CAS_630),
+ BOARD_CAS("CAS-630W", "Cellvision CAS-630W", MODEL_CAS_630W),
+ BOARD_CAS("CAS-670", "Cellvision CAS-670", MODEL_CAS_670),
+ BOARD_CAS("CAS-670W", "Cellvision CAS-670W", MODEL_CAS_670W),
+ BOARD_NFS("NFS-101U", "Cellvision NFS-101U", MODEL_NFS_101U),
+ BOARD_NFS("NFS-101WU", "Cellvision NFS-101WU", MODEL_NFS_101WU),
+ BOARD_NFS("NFS-202U", "Cellvision NFS-202U", MODEL_NFS_202U),
+ BOARD_NFS("NFS-202WU", "Cellvision NFS-202WU", MODEL_NFS_202WU),
+
+ /* Corega products */
+ BOARD_NFS("CG-NSADP", "Corega CG-NSADP", MODEL_CG_NSADP),
+ BOARD_NFS("CG-NSADPCR", "Corega CG-NSADPCR", MODEL_CG_NSADPCR),
+
+ /* D-Link products */
+ BOARD_CAS("DCS-950", "D-Link DCS-950", MODEL_DCS_950),
+ BOARD_CAS("DCS-950G", "D-Link DCS-950G", MODEL_DCS_950G),
+ BOARD_NFS("DNS-120", "D-Link DNS-120", MODEL_DNS_120),
+ BOARD_NFS("DNS-G120", "D-Link DNS-G120", MODEL_DNS_G120),
+
+ /* Digitus products */
+ BOARD_NFS("DN-7013", "Digitus DN-7013", MODEL_DN_7013),
+
+ /* Lobos products */
+ BOARD_NFS("LB-SS01TXU", "Lobos LB-SS01TXU", MODEL_LB_SS01TXU),
+
+ /* Ovislink products */
+ BOARD_NFS("MU-5000FS", "Ovislink MU-5000FS", MODEL_MU_5000FS),
+ BOARD_CAS("WL-5420CAM", "Ovislink WL-5420 CAM", MODEL_WL_5420CAM),
+ BOARD_CAS("WL-5460CAM", "Ovislink WL-5460 CAM", MODEL_WL_5460CAM),
+
+ /* Sitecom products */
+ BOARD_CAS("LN-403", "Sitecom LN-403", MODEL_LN_403),
+ BOARD_CAS("WL-401", "Sitecom WL-401", MODEL_WL_401),
+
+ /* Surecom products */
+ BOARD_CAS("EP-4001-MM", "Surecom EP-4001-MM", MODEL_EP_4001_MM),
+ BOARD_CAS("EP-4002-MM", "Surecom EP-4002-MM", MODEL_EP_4002_MM),
+ BOARD_CAS("EP-4011-MM", "Surecom EP-4011-MM", MODEL_EP_4011_MM),
+ BOARD_CAS("EP-4012-MM", "Surecom EP-4012-MM", MODEL_EP_4012_MM),
+
+ /* TrendNET products */
+ BOARD_NFS("TN-U100", "TrendNET TN-U100", MODEL_TN_U100),
+ BOARD_NFS("TN-U200", "TrendNET TN-U200", MODEL_TN_U200),
+
+ {.model = NULL}
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define WARN(fmt, ...) do { \
+ fprintf(stderr, "[%s] *** warning: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define DBG(lev, fmt, ...) do { \
+ if (verblevel < lev) \
+ break;\
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERR_FATAL -1
+#define ERR_INVALID_IMAGE -2
+
+void
+usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...] <file>\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>.\n"
+" valid <board> values:\n"
+ );
+ for (board = boards; board->model != NULL; board++){
+ fprintf(stream,
+" %-12s: %s\n",
+ board->model, board->name);
+ };
+ fprintf(stream,
+" -d don't throw error on invalid images\n"
+" -k keep invalid images\n"
+" -K <file> add kernel to the image\n"
+" -C <file> add custom filesystem to the image\n"
+" -h show this screen\n"
+"Parameters:\n"
+" <file> write output to the file <file>\n"
+ );
+
+ exit(status);
+}
+
+static inline uint32_t align(uint32_t base, uint32_t alignment)
+{
+ uint32_t ret;
+
+ if (alignment) {
+ ret = (base + alignment - 1);
+ ret &= ~(alignment-1);
+ } else {
+ ret = base;
+ }
+
+ return ret;
+}
+
+/*
+ * argument parsing
+ */
+int
+str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+
+int
+str2u16(char *arg, uint16_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) {
+ return -1;
+ }
+
+ *val = t & 0xFFFF;
+ return 0;
+}
+
+int
+str2u8(char *arg, uint8_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) {
+ return -1;
+ }
+
+ *val = t & 0xFF;
+ return 0;
+}
+
+int
+parse_arg(char *arg, char *buf, char *argv[])
+{
+ int res = 0;
+ size_t argl;
+ char *tok;
+ char **ap = &buf;
+ int i;
+
+ memset(argv, 0, MAX_ARG_COUNT * sizeof(void *));
+
+ if ((arg == NULL)) {
+ /* no arguments */
+ return 0;
+ }
+
+ argl = strlen(arg);
+ if (argl == 0) {
+ /* no arguments */
+ return 0;
+ }
+
+ if (argl >= MAX_ARG_LEN) {
+ /* argument is too long */
+ argl = MAX_ARG_LEN-1;
+ }
+
+ memcpy(buf, arg, argl);
+ buf[argl] = '\0';
+
+ for (i = 0; i < MAX_ARG_COUNT; i++) {
+ tok = strsep(ap, ":");
+ if (tok == NULL) {
+ break;
+ }
+#if 0
+ else if (tok[0] == '\0') {
+ break;
+ }
+#endif
+ argv[i] = tok;
+ res++;
+ }
+
+ return res;
+}
+
+
+int
+required_arg(char c, char *arg)
+{
+ if (arg == NULL || *arg != '-')
+ return 0;
+
+ ERR("option -%c requires an argument\n", c);
+ return ERR_FATAL;
+}
+
+
+int
+is_empty_arg(char *arg)
+{
+ int ret = 1;
+ if (arg != NULL) {
+ if (*arg) ret = 0;
+ };
+ return ret;
+}
+
+
+void
+csum8_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ for ( ; len > 0; len --) {
+ css->val += *p++;
+ }
+}
+
+
+uint16_t
+csum8_get(struct csum_state *css)
+{
+ uint8_t t;
+
+ t = css->val;
+ return ~t + 1;
+}
+
+
+void
+csum16_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ uint16_t t;
+
+ if (css->odd) {
+ t = css->tmp + (p[0]<<8);
+ css->val += LE16_TO_HOST(t);
+ css->odd = 0;
+ len--;
+ p++;
+ }
+
+ for ( ; len > 1; len -= 2, p +=2 ) {
+ t = p[0] + (p[1] << 8);
+ css->val += LE16_TO_HOST(t);
+ }
+
+ if (len == 1) {
+ css->tmp = p[0];
+ css->odd = 1;
+ }
+}
+
+
+uint16_t
+csum16_get(struct csum_state *css)
+{
+ char pad = 0;
+
+ csum16_update(&pad, 1, css);
+ return ~css->val + 1;
+}
+
+void
+csum32_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ uint32_t t;
+
+ for ( ; len > 3; len -= 4, p += 4 ) {
+ t = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
+ css->val ^= t;
+ }
+}
+
+uint32_t
+csum32_get(struct csum_state *css)
+{
+ return css->val;
+}
+
+
+void
+csum_init(struct csum_state *css, int size)
+{
+ css->val = 0;
+ css->tmp = 0;
+ css->odd = 0;
+ css->size = size;
+}
+
+void
+csum_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ switch (css->size) {
+ case CSUM_TYPE_8:
+ csum8_update(p,len,css);
+ break;
+ case CSUM_TYPE_16:
+ csum16_update(p,len,css);
+ break;
+ case CSUM_TYPE_32:
+ csum32_update(p,len,css);
+ break;
+ }
+}
+
+
+uint32_t
+csum_get(struct csum_state *css)
+{
+ uint32_t ret;
+
+ switch (css->size) {
+ case CSUM_TYPE_8:
+ ret = csum8_get(css);
+ break;
+ case CSUM_TYPE_16:
+ ret = csum16_get(css);
+ break;
+ case CSUM_TYPE_32:
+ ret = csum32_get(css);
+ }
+
+ return ret;
+}
+
+
+/*
+ * routines to write data to the output file
+ */
+int
+write_out_data(FILE *outfile, uint8_t *data, size_t len,
+ struct csum_state *css)
+{
+ errno = 0;
+
+ fwrite(data, len, 1, outfile);
+ if (errno) {
+ ERRS("unable to write output file");
+ return ERR_FATAL;
+ }
+
+ if (css) {
+ csum_update(data, len, css);
+ }
+
+ return 0;
+}
+
+
+int
+write_out_padding(FILE *outfile, size_t len, uint8_t padc,
+ struct csum_state *css)
+{
+ uint8_t buf[512];
+ size_t buflen = sizeof(buf);
+ int err;
+
+ memset(buf, padc, buflen);
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ err = write_out_data(outfile, buf, buflen, css);
+ if (err)
+ return err;
+
+ len -= buflen;
+ }
+
+ return 0;
+}
+
+
+int
+image_stat_file(struct image_desc *desc)
+{
+ struct stat st;
+ int err;
+
+ if (desc->file_name == NULL)
+ return 0;
+
+ err = stat(desc->file_name, &st);
+ if (err){
+ ERRS("stat failed on %s", desc->file_name);
+ return ERR_FATAL;
+ }
+
+ if (st.st_size > desc->out_size) {
+ WARN("file %s is too big, will be truncated to %d bytes\n",
+ desc->file_name, desc->out_size);
+ desc->file_size = desc->out_size;
+ return ERR_INVALID_IMAGE;
+ }
+
+
+ desc->file_size = st.st_size;
+ desc->out_size = align(desc->file_size,1);
+ return 0;
+}
+
+
+int
+image_writeout_file(FILE *outfile, struct image_desc *desc,
+ struct csum_state *css)
+{
+ char buf[FILE_BUF_LEN];
+ size_t buflen = sizeof(buf);
+ FILE *f;
+ size_t len;
+ int res;
+
+ if (desc->file_name == NULL)
+ return 0;
+
+ if (desc->file_size == 0)
+ return 0;
+
+ errno = 0;
+ f = fopen(desc->file_name,"r");
+ if (errno) {
+ ERRS("unable to open file: %s", desc->file_name);
+ return ERR_FATAL;
+ }
+
+ len = desc->file_size;
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ /* read data from source file */
+ errno = 0;
+ fread(buf, buflen, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file: %s", desc->file_name);
+ res = ERR_FATAL;
+ break;
+ }
+
+ res = write_out_data(outfile, buf, buflen, css);
+ if (res)
+ break;
+
+ len -= buflen;
+ }
+
+ fclose(f);
+ return res;
+}
+
+
+int
+image_writeout(FILE *outfile, struct image_desc *desc)
+{
+ int res;
+ struct csum_state css;
+ size_t padlen;
+
+ res = 0;
+
+ if (!desc->file_size)
+ return 0;
+
+ DBG(2, "writing image, file=%s, file_size=%d\n",
+ desc->file_name, desc->file_size);
+
+ csum_init(&css, CSUM_TYPE_32);
+
+ res = image_writeout_file(outfile, desc, &css);
+ if (res)
+ return res;
+
+ /* write padding data if neccesary */
+ padlen = desc->out_size - desc->file_size;
+ DBG(1,"padding desc, length=%zu", padlen);
+ res = write_out_padding(outfile, padlen, desc->padc, &css);
+
+ desc->csum = csum_get(&css);
+
+ return res;
+}
+
+
+int
+write_out_header(FILE *outfile)
+{
+ union file_hdr tmp;
+ int res;
+
+ errno = 0;
+ if (fseek(outfile, 0, SEEK_SET) != 0) {
+ ERRS("fseek failed on output file");
+ return ERR_FATAL;
+ }
+
+ switch (board->header_type) {
+ case HEADER_TYPE_CAS:
+ tmp.cas.type = HOST_TO_LE32(header.cas.type);
+ tmp.cas.id = HOST_TO_LE32(header.cas.id);
+ tmp.cas.kernel_offs = HOST_TO_LE32(sizeof(tmp.cas));
+ tmp.cas.kernel_size = HOST_TO_LE32(kernel_image.out_size);
+ tmp.cas.kernel_csum = HOST_TO_LE32(kernel_image.csum);
+ tmp.cas.magic1 = HOST_TO_LE32(CAS_MAGIC1);
+ tmp.cas.magic2 = HOST_TO_LE32(CAS_MAGIC2);
+ tmp.cas.magic3 = HOST_TO_LE32(CAS_MAGIC3);
+ res = write_out_data(outfile, (uint8_t *)&tmp.cas,
+ sizeof(tmp.cas), NULL);
+ break;
+ case HEADER_TYPE_NFS:
+ tmp.nfs.type = HOST_TO_LE32(header.nfs.type);
+ tmp.nfs.id = HOST_TO_LE32(header.nfs.id);
+ tmp.nfs.kernel_offs = HOST_TO_LE32(sizeof(tmp.nfs));
+ tmp.nfs.kernel_size = HOST_TO_LE32(kernel_image.out_size);
+ tmp.nfs.kernel_csum = HOST_TO_LE32(kernel_image.csum);
+ tmp.nfs.fs_offs = HOST_TO_LE32(sizeof(tmp.nfs)
+ + kernel_image.out_size);
+ tmp.nfs.fs_size = HOST_TO_LE32(fs_image.out_size);
+ tmp.nfs.fs_csum = HOST_TO_LE32(fs_image.csum);
+ res = write_out_data(outfile, (uint8_t *)&tmp.nfs,
+ sizeof(tmp.nfs), NULL);
+ break;
+ }
+
+ return res;
+}
+
+int
+write_out_images(FILE *outfile)
+{
+ struct image_desc *desc;
+ int i, res;
+
+ res = image_writeout(outfile, &kernel_image);
+ if (res)
+ return res;
+
+ res = image_writeout(outfile, &fs_image);
+ if (res)
+ return res;
+
+ return 0;
+}
+
+
+struct board_info *
+find_board(char *model)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->model != NULL; board++){
+ if (strcasecmp(model, board->model) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+
+int
+parse_opt_board(char ch, char *arg)
+{
+
+ DBG(1,"parsing board option: -%c %s", ch, arg);
+
+ if (board != NULL) {
+ ERR("only one board option allowed");
+ return ERR_FATAL;
+ }
+
+ if (required_arg(ch, arg))
+ return ERR_FATAL;
+
+ board = find_board(arg);
+ if (board == NULL){
+ ERR("invalid/unknown board specified: %s", arg);
+ return ERR_FATAL;
+ }
+
+ switch (board->header_type) {
+ case HEADER_TYPE_CAS:
+ header.cas.type = HEADER_TYPE_CAS;
+ header.cas.id = board->id;
+ break;
+ case HEADER_TYPE_NFS:
+ header.nfs.type = HEADER_TYPE_NFS;
+ header.nfs.id = board->id;
+ break;
+ default:
+ ERR("internal error, unknown header type\n");
+ return ERR_FATAL;
+ }
+
+ return 0;
+}
+
+
+int
+parse_opt_image(char ch, char *arg)
+{
+ char buf[MAX_ARG_LEN];
+ char *argv[MAX_ARG_COUNT];
+ int argc;
+ char *p;
+ struct image_desc *desc = NULL;
+ int i;
+
+ switch (ch) {
+ case 'K':
+ if (kernel_image.file_name) {
+ WARN("only one kernel option allowed");
+ break;
+ }
+ desc = &kernel_image;
+ break;
+ case 'F':
+ if (fs_image.file_name) {
+ WARN("only one fs option allowed");
+ break;
+ }
+ desc = &fs_image;
+ break;
+ }
+
+ if (!desc)
+ return ERR_FATAL;
+
+ argc = parse_arg(arg, buf, argv);
+
+ i = 0;
+ p = argv[i++];
+ if (!is_empty_arg(p)) {
+ desc->file_name = strdup(p);
+ if (desc->file_name == NULL) {
+ ERR("not enough memory");
+ return ERR_FATAL;
+ }
+ } else {
+ ERR("no file specified for option %c", ch);
+ return ERR_FATAL;
+ }
+
+ return 0;
+}
+
+
+int
+process_images(void)
+{
+ struct image_desc *desc;
+ uint32_t offs = 0;
+ int i;
+ int res;
+
+ kernel_image.out_size = board->max_kernel_size;
+ kernel_image.padc = DEFAULT_PADC;
+ res = image_stat_file(&kernel_image);
+ if (res)
+ return res;
+
+ if (!fs_image.file_name)
+ return 0;
+
+ fs_image.out_size = board->max_fs_size;
+ fs_image.padc = DEFAULT_PADC;
+ res = image_stat_file(&fs_image);
+ if (res)
+ return res;
+
+ return 0;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int optinvalid = 0; /* flag for invalid option */
+ int c;
+ int res = ERR_FATAL;
+
+ FILE *outfile;
+
+ progname=basename(argv[0]);
+
+ opterr = 0; /* could not print standard getopt error messages */
+ while ( 1 ) {
+ optinvalid = 0;
+
+ c = getopt(argc, argv, "B:C:dhK:r:vw:x:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'B':
+ optinvalid = parse_opt_board(c,optarg);
+ break;
+ case 'd':
+ invalid_causes_error = 0;
+ break;
+ case 'C':
+ case 'K':
+ optinvalid = parse_opt_image(c,optarg);
+ break;
+ case 'k':
+ keep_invalid_images = 1;
+ break;
+ case 'v':
+ verblevel++;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ optinvalid = 1;
+ break;
+ }
+ if (optinvalid != 0 ){
+ ERR("invalid option: -%c", optopt);
+ goto out;
+ }
+ }
+
+ if (board == NULL) {
+ ERR("no board specified");
+ goto out;
+ }
+
+ if (optind == argc) {
+ ERR("no output file specified");
+ goto out;
+ }
+
+ ofname = argv[optind++];
+
+ if (optind < argc) {
+ ERR("invalid option: %s", argv[optind]);
+ goto out;
+ }
+
+ res = process_images();
+ if (res == ERR_FATAL)
+ goto out;
+
+ if (res == ERR_INVALID_IMAGE) {
+ if (invalid_causes_error)
+ res = ERR_FATAL;
+
+ if (keep_invalid_images == 0) {
+ WARN("generation of invalid images \"%s\" disabled", ofname);
+ goto out;
+ }
+
+ WARN("generating invalid image: \"%s\"", ofname);
+ }
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ res = ERR_FATAL;
+ goto out;
+ }
+
+ if (write_out_header(outfile) != 0) {
+ res = ERR_FATAL;
+ goto out_flush;
+ }
+
+ if (write_out_images(outfile) != 0) {
+ res = ERR_FATAL;
+ goto out_flush;
+ }
+
+ if (write_out_header(outfile) != 0) {
+ res = ERR_FATAL;
+ goto out_flush;
+ }
+
+ DBG(1,"Image file %s completed.", ofname);
+
+out_flush:
+ fflush(outfile);
+ fclose(outfile);
+ if (res == ERR_FATAL) {
+ unlink(ofname);
+ }
+out:
+ if (res == ERR_FATAL)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/mkchkimg.c b/tools/firmware-utils/src/mkchkimg.c
new file mode 100644
index 0000000..e152f7d
--- /dev/null
+++ b/tools/firmware-utils/src/mkchkimg.c
@@ -0,0 +1,327 @@
+/*
+ * Make CHK Image
+ *
+ * This utility creates Netgear .chk files.
+ *
+ * Copyright (C) 2008 Dave C. Reeve <Dave.Reeve@dreeve.org>
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#define BUF_LEN (2048)
+
+#define MAX_BOARD_ID_LEN (64)
+
+struct chk_header {
+ uint32_t magic;
+ uint32_t header_len;
+ uint8_t reserved[8];
+ uint32_t kernel_chksum;
+ uint32_t rootfs_chksum;
+ uint32_t kernel_len;
+ uint32_t rootfs_len;
+ uint32_t image_chksum;
+ uint32_t header_chksum;
+ /* char board_id[] - upto MAX_BOARD_ID_LEN */
+};
+
+static void __attribute__ ((format (printf, 2, 3)))
+fatal_error (int maybe_errno, const char * format, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, "mkchkimg: ");
+ va_start (ap, format);
+ vfprintf (stderr, format, ap);
+ va_end (ap);
+
+ if (maybe_errno) {
+ fprintf (stderr, ": %s\n", strerror (maybe_errno));
+ } else {
+ fprintf (stderr, "\n");
+ }
+
+ exit (EXIT_FAILURE);
+}
+
+static void __attribute__ ((format (printf, 1, 2)))
+message (const char * format, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, "mkchkimg: ");
+ va_start (ap, format);
+ vfprintf (stderr, format, ap);
+ va_end (ap);
+ fprintf (stderr, "\n");
+}
+
+struct ngr_checksum {
+ uint32_t c0;
+ uint32_t c1;
+};
+
+static inline void
+netgear_checksum_init (struct ngr_checksum * c)
+{
+ c->c0 = c->c1 = 0;
+}
+
+static inline void
+netgear_checksum_add (struct ngr_checksum * c, unsigned char * buf, size_t len)
+{
+ size_t i;
+
+ for (i=0; i<len; i++) {
+ c->c0 += buf[i] & 0xff;
+ c->c1 += c->c0;
+ }
+}
+
+static inline unsigned long
+netgear_checksum_fini (struct ngr_checksum * c)
+{
+ uint32_t b, checksum;
+
+ b = (c->c0 & 65535) + ((c->c0 >> 16) & 65535);
+ c->c0 = ((b >> 16) + b) & 65535;
+ b = (c->c1 & 65535) + ((c->c1 >> 16) & 65535);
+ c->c1 = ((b >> 16) + b) & 65535;
+ checksum = ((c->c1 << 16) | c->c0);
+ return checksum;
+}
+
+static void
+print_help (void)
+{
+ fprintf (stderr, "Usage: mkchkimg -o output -k kernel [-f filesys] [-b board_id] [-r region]\n");
+}
+
+int
+main (int argc, char * argv[])
+{
+ int opt;
+ char * ptr;
+ size_t len;
+ size_t header_len;
+ struct chk_header * hdr;
+ struct ngr_checksum chk_part, chk_whole;
+ char buf[BUF_LEN];
+ char * output_file, * kern_file, * fs_file;
+ FILE * out_fp, * kern_fp, * fs_fp;
+ char * board_id;
+ unsigned long region;
+
+ /* Default values */
+ board_id = "U12H072T00_NETGEAR";
+ region = 1; /* 1=WW, 2=NA */
+ output_file = NULL;
+ kern_file = NULL;
+ fs_file = NULL;
+ fs_fp = NULL;
+
+ while ((opt = getopt (argc, argv, ":b:r:k:f:o:h")) != -1) {
+ switch (opt) {
+ case 'b':
+ /* Board Identity */
+ if (strlen (optarg) > MAX_BOARD_ID_LEN) {
+ fatal_error (0, "Board lenght exceeds %d",
+ MAX_BOARD_ID_LEN);
+ }
+ board_id = optarg;
+ break;
+
+ case 'r':
+ /* Region */
+ errno = 0;
+ region = strtoul (optarg, &ptr, 0);
+ if (errno || ptr==optarg || *ptr!='\0') {
+ fatal_error (0, "Cannot parse region %s", optarg);
+ }
+ if (region > 0xff) {
+ fatal_error (0, "Region cannot exceed 0xff");
+ }
+ break;
+
+ case 'k':
+ /* Kernel */
+ kern_file = optarg;
+ break;
+
+ case 'f':
+ /* Filing System */
+ fs_file = optarg;
+ break;
+
+ case 'o':
+ /* Output file */
+ output_file = optarg;
+ break;
+
+ case 'h':
+ print_help ();
+ return EXIT_SUCCESS;
+
+ case ':':
+ print_help ();
+ fatal_error (0, "Option -%c missing argument", optopt);
+ break;
+
+ case '?':
+ print_help ();
+ fatal_error (0, "Unknown argument -%c", optopt);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Check we have all the options expected */
+ if (!kern_file) {
+ print_help ();
+ fatal_error (0, "Kernel file expected");
+ }
+ if (!output_file) {
+ print_help ();
+ fatal_error (0, "Output file required");
+ }
+ message ("Netgear CHK writer - v0.1");
+
+ /* Open the input file */
+ kern_fp = fopen (kern_file, "r");
+ if (!kern_fp) {
+ fatal_error (errno, "Cannot open %s", kern_file);
+ }
+
+ /* Open the fs file, if specified */
+ if (fs_file) {
+ fs_fp = fopen (fs_file, "r");
+ if (!fs_fp) {
+ fatal_error (errno, "Cannot open %s", fs_file);
+ }
+ }
+
+ /* Open the output file */
+ out_fp = fopen (output_file, "w+");
+ if (!out_fp) {
+ fatal_error (errno, "Cannot open %s", output_file);
+ }
+
+ /* Write zeros when the chk header will be */
+ buf[0] = '\0';
+ header_len = sizeof (struct chk_header) + strlen (board_id);
+ if (fwrite (buf, 1, header_len, out_fp) != header_len) {
+ fatal_error (errno, "Cannot write header");
+ }
+
+ /* Allocate storage for header, we fill in as we go */
+ hdr = malloc (sizeof (struct chk_header));
+ if (!hdr) {
+ fatal_error (0, "malloc failed");
+ }
+ bzero (hdr, sizeof (struct chk_header));
+
+ /* Fill in known values */
+ hdr->magic = htonl (0x2a23245e);
+ hdr->header_len = htonl(header_len);
+ hdr->reserved[0] = (unsigned char)(region & 0xff);
+ hdr->reserved[1] = 1; /* Major */
+ hdr->reserved[2] = 1; /* Minor */
+ hdr->reserved[3] = 99; /* Build */
+ hdr->reserved[4] = 0; /* Unknown t1 ? was 1 */
+ hdr->reserved[5] = 0; /* Unknonw t2 ? was 0 */
+ hdr->reserved[6] = 0; /* Unknonw t3 ? was 1 */
+ hdr->reserved[7] = 0; /* Unused ? */
+ message (" Board Id: %s", board_id);
+ message (" Region: %s", region == 1 ? "World Wide (WW)"
+ : (region == 2 ? "North America (NA)" : "Unknown"));
+
+ /* Copy the trx file, calculating the checksum as we go */
+ netgear_checksum_init (&chk_part);
+ netgear_checksum_init (&chk_whole);
+ while (!feof (kern_fp)) {
+ len = fread (buf, 1, BUF_LEN, kern_fp);
+ if (len < 1) {
+ break;
+ }
+ if (fwrite (buf, len, 1, out_fp) != 1) {
+ fatal_error (errno, "Write error");
+ }
+ hdr->kernel_len += len;
+ netgear_checksum_add (&chk_part, (unsigned char *)buf, len);
+ netgear_checksum_add (&chk_whole, (unsigned char *)buf, len);
+ }
+ hdr->kernel_chksum = netgear_checksum_fini (&chk_part);
+ message (" Kernel Len: %u", hdr->kernel_len);
+ message ("Kernel Checksum: 0x%08x", hdr->kernel_chksum);
+ hdr->kernel_len = htonl (hdr->kernel_len);
+ hdr->kernel_chksum = htonl (hdr->kernel_chksum);
+
+ /* Now copy the root fs, calculating the checksum as we go */
+ if (fs_fp) {
+ netgear_checksum_init (&chk_part);
+ while (!feof (fs_fp)) {
+ len = fread (buf, 1, BUF_LEN, fs_fp);
+ if (len < 1) {
+ break;
+ }
+ if (fwrite (buf, len, 1, out_fp) != 1) {
+ fatal_error (errno, "Write error");
+ }
+ hdr->rootfs_len += len;
+ netgear_checksum_add (&chk_part, (unsigned char *)buf, len);
+ netgear_checksum_add (&chk_whole, (unsigned char *)buf, len);
+ }
+ hdr->rootfs_chksum = (netgear_checksum_fini (&chk_part));
+ message (" Rootfs Len: %u", hdr->rootfs_len);
+ message ("Rootfs Checksum: 0x%08x", hdr->rootfs_chksum);
+ hdr->rootfs_len = htonl (hdr->rootfs_len);
+ hdr->rootfs_chksum = htonl (hdr->rootfs_chksum);
+ }
+
+ /* Calcautate the image checksum */
+ hdr->image_chksum = netgear_checksum_fini (&chk_whole);
+ message (" Image Checksum: 0x%08x", hdr->image_chksum);
+ hdr->image_chksum = htonl (hdr->image_chksum);
+
+ /* Calculate the header checksum */
+ netgear_checksum_init (&chk_part);
+ netgear_checksum_add (&chk_part, (unsigned char *)hdr,
+ sizeof (struct chk_header));
+ netgear_checksum_add (&chk_part, (unsigned char *)board_id,
+ strlen (board_id));
+ hdr->header_chksum = htonl (netgear_checksum_fini (&chk_part));
+
+ /* Finally rewind the output and write headers */
+ rewind (out_fp);
+ if (fwrite (hdr, sizeof (struct chk_header), 1, out_fp) != 1) {
+ fatal_error (errno, "Cannot write header");
+ }
+ if (fwrite (board_id, strlen (board_id), 1, out_fp) != 1) {
+ fatal_error (errno, "Cannot write board id");
+ }
+
+ /* Success */
+ return EXIT_SUCCESS;
+}
+
diff --git a/tools/firmware-utils/src/mkcsysimg.c b/tools/firmware-utils/src/mkcsysimg.c
new file mode 100644
index 0000000..77fbbaa
--- /dev/null
+++ b/tools/firmware-utils/src/mkcsysimg.c
@@ -0,0 +1,1157 @@
+/*
+ *
+ * Copyright (C) 2007-2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program was based on the code found in various Linux
+ * source tarballs released by Edimax for it's devices.
+ * Original author: David Hsu <davidhsu@realtek.com.tw>
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <endian.h> /* for __BYTE_ORDER */
+#if defined(__CYGWIN__)
+# include <byteswap.h>
+#endif
+
+#include "csysimg.h"
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define HOST_TO_LE16(x) (x)
+# define HOST_TO_LE32(x) (x)
+# define LE16_TO_HOST(x) (x)
+# define LE32_TO_HOST(x) (x)
+#else
+# define HOST_TO_LE16(x) bswap_16(x)
+# define HOST_TO_LE32(x) bswap_32(x)
+# define LE16_TO_HOST(x) bswap_16(x)
+# define LE32_TO_HOST(x) bswap_32(x)
+#endif
+
+#define MAX_NUM_BLOCKS 8
+#define MAX_ARG_COUNT 32
+#define MAX_ARG_LEN 1024
+#define FILE_BUF_LEN (16*1024)
+#define CSYS_PADC 0xFF
+
+#define BLOCK_TYPE_BOOT 0
+#define BLOCK_TYPE_CONF 1
+#define BLOCK_TYPE_WEBP 2
+#define BLOCK_TYPE_CODE 3
+#define BLOCK_TYPE_XTRA 4
+
+#define DEFAULT_BLOCK_ALIGN 0x10000U
+
+#define CSUM_SIZE_NONE 0
+#define CSUM_SIZE_8 1
+#define CSUM_SIZE_16 2
+
+
+struct csum_state{
+ int size;
+ uint16_t val;
+ uint16_t tmp;
+ int odd;
+};
+
+
+struct csys_block {
+ int type; /* type of the block */
+
+ int need_file;
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+
+ unsigned char sig[SIG_LEN];
+ uint32_t addr;
+ int addr_set;
+ uint32_t align;
+ int align_set;
+ uint8_t padc;
+
+ uint32_t size;
+ uint32_t size_hdr;
+ uint32_t size_csum;
+ uint32_t size_avail;
+
+ struct csum_state *css;
+};
+
+
+struct board_info {
+ char *model;
+ char *name;
+ uint32_t flash_size;
+
+ char sig_boot[SIG_LEN];
+ char sig_conf[SIG_LEN];
+ char sig_webp[SIG_LEN];
+
+ uint32_t boot_size;
+ uint32_t conf_size;
+ uint32_t webp_size;
+ uint32_t webp_size_max;
+ uint32_t code_size;
+
+ uint32_t addr_code;
+ uint32_t addr_webp;
+};
+
+#define BOARD(m, n, f, sigb, sigw, bs, cs, ws, ac, aw) {\
+ .model = m, .name = n, .flash_size = f<<20, \
+ .sig_boot = sigb, .sig_conf = SIG_CONF, .sig_webp = sigw, \
+ .boot_size = bs, .conf_size = cs, \
+ .webp_size = ws, .webp_size_max = 3*0x10000, \
+ .addr_code = ac, .addr_webp = aw \
+ }
+
+#define BOARD_ADM(m,n,f, sigw) BOARD(m,n,f, ADM_BOOT_SIG, sigw, \
+ ADM_BOOT_SIZE, ADM_CONF_SIZE, ADM_WEBP_SIZE, \
+ ADM_CODE_ADDR, ADM_WEBP_ADDR)
+
+
+/*
+ * Globals
+ */
+char *progname;
+char *ofname = NULL;
+int verblevel = 0;
+int invalid_causes_error = 1;
+int keep_invalid_images = 0;
+
+struct board_info *board = NULL;
+
+struct csys_block *boot_block = NULL;
+struct csys_block *conf_block = NULL;
+struct csys_block *webp_block = NULL;
+struct csys_block *code_block = NULL;
+
+struct csys_block blocks[MAX_NUM_BLOCKS];
+int num_blocks = 0;
+
+static struct board_info boards[] = {
+ /* The original Edimax products */
+ BOARD_ADM("BR-6104K", "Edimax BR-6104K", 2, SIG_BR6104K),
+ BOARD_ADM("BR-6104KP", "Edimax BR-6104KP", 2, SIG_BR6104KP),
+ BOARD_ADM("BR-6104Wg", "Edimax BR-6104Wg", 2, SIG_BR6104Wg),
+ BOARD_ADM("BR-6114WG", "Edimax BR-6114WG", 2, SIG_BR6114WG),
+ BOARD_ADM("BR-6524K", "Edimax BR-6524K", 2, SIG_BR6524K),
+ BOARD_ADM("BR-6524KP", "Edimax BR-6524KP", 2, SIG_BR6524KP),
+ BOARD_ADM("BR-6524N", "Edimax BR-6524N", 2, SIG_BR6524N),
+ BOARD_ADM("BR-6524WG", "Edimax BR-6524WG", 4, SIG_BR6524WG),
+ BOARD_ADM("BR-6524WP", "Edimax BR-6524WP", 4, SIG_BR6524WP),
+ BOARD_ADM("BR-6541K", "Edimax BR-6541K", 2, SIG_BR6541K),
+ BOARD_ADM("BR-6541KP", "Edimax BR-6541K", 2, SIG_BR6541KP),
+ BOARD_ADM("BR-6541WP", "Edimax BR-6541WP", 4, SIG_BR6541WP),
+ BOARD_ADM("EW-7207APg", "Edimax EW-7207APg", 2, SIG_EW7207APg),
+ BOARD_ADM("PS-1205UWg", "Edimax PS-1205UWg", 2, SIG_PS1205UWg),
+ BOARD_ADM("PS-3205U", "Edimax PS-3205U", 2, SIG_PS3205U),
+ BOARD_ADM("PS-3205UWg", "Edimax PS-3205UWg", 2, SIG_PS3205UWg),
+
+ /* Hawking products */
+ BOARD_ADM("H2BR4", "Hawking H2BR4", 2, SIG_H2BR4),
+ BOARD_ADM("H2WR54G", "Hawking H2WR54G", 4, SIG_H2WR54G),
+
+ /* Planet products */
+ BOARD_ADM("XRT-401D", "Planet XRT-401D", 2, SIG_XRT401D),
+ BOARD_ADM("XRT-402D", "Planet XRT-402D", 2, SIG_XRT402D),
+
+ /* Conceptronic products */
+ BOARD_ADM("C54BSR4", "Conceptronic C54BSR4", 2, SIG_C54BSR4),
+
+ /* OSBRiDGE products */
+ BOARD_ADM("5GXi", "OSBDRiDGE 5GXi", 2, SIG_5GXI),
+
+ {.model = NULL}
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", progname, ## __VA_ARGS__ \
+ , strerror(save)); \
+} while (0)
+
+#define WARN(fmt, ...) do { \
+ fprintf(stderr, "[%s] *** warning: " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define DBG(lev, fmt, ...) do { \
+ if (verblevel < lev) \
+ break;\
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERR_FATAL -1
+#define ERR_INVALID_IMAGE -2
+
+void
+usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...] <file>\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>.\n"
+" valid <board> values:\n"
+ );
+ for (board = boards; board->model != NULL; board++){
+ fprintf(stream,
+" %-12s: %s\n",
+ board->model, board->name);
+ };
+ fprintf(stream,
+" -d don't throw error on invalid images\n"
+" -k keep invalid images\n"
+" -b <file>[:<align>[:<padc>]]\n"
+" add boot code to the image\n"
+" -c <file>[:<align>[:<padc>]]\n"
+" add configuration settings to the image\n"
+" -r <file>:[<addr>][:<align>[:<padc>]]\n"
+" add runtime code to the image\n"
+" -w [<file>:[<addr>][:<align>[:<padc>]]]\n"
+" add webpages to the image\n"
+" -x <file>[:<align>[:<padc>]]\n"
+" add extra data at the end of the image\n"
+" -h show this screen\n"
+"Parameters:\n"
+" <file> write output to the file <file>\n"
+ );
+
+ exit(status);
+}
+
+static inline uint32_t align(uint32_t base, uint32_t alignment)
+{
+ uint32_t ret;
+
+ if (alignment) {
+ ret = (base + alignment - 1);
+ ret &= ~(alignment-1);
+ } else {
+ ret = base;
+ }
+
+ return ret;
+}
+
+/*
+ * argument parsing
+ */
+int
+str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+
+int
+str2u16(char *arg, uint16_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) {
+ return -1;
+ }
+
+ *val = t & 0xFFFF;
+ return 0;
+}
+
+int
+str2u8(char *arg, uint8_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) {
+ return -1;
+ }
+
+ *val = t & 0xFF;
+ return 0;
+}
+
+int
+str2sig(char *arg, uint32_t *sig)
+{
+ if (strlen(arg) != 4)
+ return -1;
+
+ *sig = arg[0] | (arg[1] << 8) | (arg[2] << 16) | (arg[3] << 24);
+
+ return 0;
+}
+
+
+int
+parse_arg(char *arg, char *buf, char *argv[])
+{
+ int res = 0;
+ size_t argl;
+ char *tok;
+ char **ap = &buf;
+ int i;
+
+ memset(argv, 0, MAX_ARG_COUNT * sizeof(void *));
+
+ if ((arg == NULL)) {
+ /* no arguments */
+ return 0;
+ }
+
+ argl = strlen(arg);
+ if (argl == 0) {
+ /* no arguments */
+ return 0;
+ }
+
+ if (argl >= MAX_ARG_LEN) {
+ /* argument is too long */
+ argl = MAX_ARG_LEN-1;
+ }
+
+ memcpy(buf, arg, argl);
+ buf[argl] = '\0';
+
+ for (i = 0; i < MAX_ARG_COUNT; i++) {
+ tok = strsep(ap, ":");
+ if (tok == NULL) {
+ break;
+ }
+#if 0
+ else if (tok[0] == '\0') {
+ break;
+ }
+#endif
+ argv[i] = tok;
+ res++;
+ }
+
+ return res;
+}
+
+
+int
+required_arg(char c, char *arg)
+{
+ if (arg == NULL || *arg != '-')
+ return 0;
+
+ ERR("option -%c requires an argument\n", c);
+ return ERR_FATAL;
+}
+
+
+int
+is_empty_arg(char *arg)
+{
+ int ret = 1;
+ if (arg != NULL) {
+ if (*arg) ret = 0;
+ };
+ return ret;
+}
+
+
+void
+csum8_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ for ( ; len > 0; len --) {
+ css->val += *p++;
+ }
+}
+
+
+uint16_t
+csum8_get(struct csum_state *css)
+{
+ uint8_t t;
+
+ t = css->val;
+ return ~t + 1;
+}
+
+
+void
+csum16_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ uint16_t t;
+
+ if (css->odd) {
+ t = css->tmp + (p[0]<<8);
+ css->val += LE16_TO_HOST(t);
+ css->odd = 0;
+ len--;
+ p++;
+ }
+
+ for ( ; len > 1; len -= 2, p +=2 ) {
+ t = p[0] + (p[1] << 8);
+ css->val += LE16_TO_HOST(t);
+ }
+
+ if (len == 1) {
+ css->tmp = p[0];
+ css->odd = 1;
+ }
+}
+
+
+uint16_t
+csum16_get(struct csum_state *css)
+{
+ char pad = 0;
+
+ csum16_update(&pad, 1, css);
+ return ~css->val + 1;
+}
+
+
+void
+csum_init(struct csum_state *css, int size)
+{
+ css->val = 0;
+ css->tmp = 0;
+ css->odd = 0;
+ css->size = size;
+}
+
+
+void
+csum_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ switch (css->size) {
+ case CSUM_SIZE_8:
+ csum8_update(p,len,css);
+ break;
+ case CSUM_SIZE_16:
+ csum16_update(p,len,css);
+ break;
+ }
+}
+
+
+uint16_t
+csum_get(struct csum_state *css)
+{
+ uint16_t ret;
+
+ switch (css->size) {
+ case CSUM_SIZE_8:
+ ret = csum8_get(css);
+ break;
+ case CSUM_SIZE_16:
+ ret = csum16_get(css);
+ break;
+ }
+
+ return ret;
+}
+
+
+/*
+ * routines to write data to the output file
+ */
+int
+write_out_data(FILE *outfile, uint8_t *data, size_t len,
+ struct csum_state *css)
+{
+ errno = 0;
+
+ fwrite(data, len, 1, outfile);
+ if (errno) {
+ ERRS("unable to write output file");
+ return ERR_FATAL;
+ }
+
+ if (css) {
+ csum_update(data, len, css);
+ }
+
+ return 0;
+}
+
+
+int
+write_out_padding(FILE *outfile, size_t len, uint8_t padc,
+ struct csum_state *css)
+{
+ uint8_t buf[512];
+ size_t buflen = sizeof(buf);
+ int err;
+
+ memset(buf, padc, buflen);
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ err = write_out_data(outfile, buf, buflen, css);
+ if (err)
+ return err;
+
+ len -= buflen;
+ }
+
+ return 0;
+}
+
+
+int
+block_stat_file(struct csys_block *block)
+{
+ struct stat st;
+ int err;
+
+ if (block->file_name == NULL)
+ return 0;
+
+ err = stat(block->file_name, &st);
+ if (err){
+ ERRS("stat failed on %s", block->file_name);
+ return ERR_FATAL;
+ }
+
+ block->file_size = st.st_size;
+ return 0;
+}
+
+
+int
+block_writeout_hdr(FILE *outfile, struct csys_block *block)
+{
+ struct csys_header hdr;
+ int res;
+
+ if (block->size_hdr == 0)
+ return 0;
+
+ /* setup header fields */
+ memcpy(hdr.sig, block->sig, 4);
+ hdr.addr = HOST_TO_LE32(block->addr);
+ hdr.size = HOST_TO_LE32(block->size - block->size_hdr - block->size_csum);
+
+ DBG(1,"writing header for block");
+ res = write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr),NULL);
+ return res;
+
+}
+
+
+int
+block_writeout_file(FILE *outfile, struct csys_block *block)
+{
+ char buf[FILE_BUF_LEN];
+ size_t buflen = sizeof(buf);
+ FILE *f;
+ size_t len;
+ int res;
+
+ if (block->file_name == NULL)
+ return 0;
+
+ if (block->file_size == 0)
+ return 0;
+
+ errno = 0;
+ f = fopen(block->file_name,"r");
+ if (errno) {
+ ERRS("unable to open file: %s", block->file_name);
+ return ERR_FATAL;
+ }
+
+ len = block->file_size;
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ /* read data from source file */
+ errno = 0;
+ fread(buf, buflen, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file: %s", block->file_name);
+ res = ERR_FATAL;
+ break;
+ }
+
+ res = write_out_data(outfile, buf, buflen, block->css);
+ if (res)
+ break;
+
+ len -= buflen;
+ }
+
+ fclose(f);
+ return res;
+}
+
+
+int
+block_writeout_data(FILE *outfile, struct csys_block *block)
+{
+ int res;
+ size_t padlen;
+
+ res = block_writeout_file(outfile, block);
+ if (res)
+ return res;
+
+ /* write padding data if neccesary */
+ padlen = block->size_avail - block->file_size;
+ DBG(1,"padding block, length=%zu", padlen);
+ res = write_out_padding(outfile, padlen, block->padc, block->css);
+
+ return res;
+}
+
+
+int
+block_writeout_csum(FILE *outfile, struct csys_block *block)
+{
+ uint16_t csum;
+ int res;
+
+ if (block->size_csum == 0)
+ return 0;
+
+ DBG(1,"writing checksum for block");
+ csum = HOST_TO_LE16(csum_get(block->css));
+ res = write_out_data(outfile, (uint8_t *)&csum, block->size_csum, NULL);
+
+ return res;
+}
+
+
+int
+block_writeout(FILE *outfile, struct csys_block *block)
+{
+ int res;
+ struct csum_state css;
+
+ res = 0;
+
+ if (block == NULL)
+ return res;
+
+ block->css = NULL;
+
+ DBG(2, "writing block, file=%s, file_size=%d, space=%d",
+ block->file_name, block->file_size, block->size_avail);
+ res = block_writeout_hdr(outfile, block);
+ if (res)
+ return res;
+
+ if (block->size_csum != 0) {
+ block->css = &css;
+ csum_init(&css, block->size_csum);
+ }
+
+ res = block_writeout_data(outfile, block);
+ if (res)
+ return res;
+
+ res = block_writeout_csum(outfile, block);
+ if (res)
+ return res;
+
+ return res;
+}
+
+
+int
+write_out_blocks(FILE *outfile)
+{
+ struct csys_block *block;
+ int i, res;
+
+ res = block_writeout(outfile, boot_block);
+ if (res)
+ return res;
+
+ res = block_writeout(outfile, conf_block);
+ if (res)
+ return res;
+
+ res = block_writeout(outfile, webp_block);
+ if (res)
+ return res;
+
+ res = block_writeout(outfile, code_block);
+ if (res)
+ return res;
+
+ res = 0;
+ for (i=0; i < num_blocks; i++) {
+ block = &blocks[i];
+
+ if (block->type != BLOCK_TYPE_XTRA)
+ continue;
+
+ res = block_writeout(outfile, block);
+ if (res)
+ break;
+ }
+
+ return res;
+}
+
+
+struct board_info *
+find_board(char *model)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->model != NULL; board++){
+ if (strcasecmp(model, board->model) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+
+int
+parse_opt_board(char ch, char *arg)
+{
+
+ DBG(1,"parsing board option: -%c %s", ch, arg);
+
+ if (board != NULL) {
+ ERR("only one board option allowed");
+ return ERR_FATAL;
+ }
+
+ if (required_arg(ch, arg))
+ return ERR_FATAL;
+
+ board = find_board(arg);
+ if (board == NULL){
+ ERR("invalid/unknown board specified: %s", arg);
+ return ERR_FATAL;
+ }
+
+ return 0;
+}
+
+
+int
+parse_opt_block(char ch, char *arg)
+{
+ char buf[MAX_ARG_LEN];
+ char *argv[MAX_ARG_COUNT];
+ int argc;
+ char *p;
+ struct csys_block *block;
+ int i;
+
+ if ( num_blocks > MAX_NUM_BLOCKS ) {
+ ERR("too many blocks specified");
+ return ERR_FATAL;
+ }
+
+ block = &blocks[num_blocks];
+
+ /* setup default field values */
+ block->need_file = 1;
+ block->padc = 0xFF;
+
+ switch (ch) {
+ case 'b':
+ if (boot_block) {
+ WARN("only one boot block allowed");
+ break;
+ }
+ block->type = BLOCK_TYPE_BOOT;
+ boot_block = block;
+ break;
+ case 'c':
+ if (conf_block) {
+ WARN("only one config block allowed");
+ break;
+ }
+ block->type = BLOCK_TYPE_CONF;
+ conf_block = block;
+ break;
+ case 'w':
+ if (webp_block) {
+ WARN("only one web block allowed");
+ break;
+ }
+ block->type = BLOCK_TYPE_WEBP;
+ block->size_hdr = sizeof(struct csys_header);
+ block->size_csum = CSUM_SIZE_8;
+ block->need_file = 0;
+ webp_block = block;
+ break;
+ case 'r':
+ if (code_block) {
+ WARN("only one runtime block allowed");
+ break;
+ }
+ block->type = BLOCK_TYPE_CODE;
+ block->size_hdr = sizeof(struct csys_header);
+ block->size_csum = CSUM_SIZE_16;
+ code_block = block;
+ break;
+ case 'x':
+ block->type = BLOCK_TYPE_XTRA;
+ break;
+ default:
+ ERR("unknown block type \"%c\"", ch);
+ return ERR_FATAL;
+ }
+
+ argc = parse_arg(arg, buf, argv);
+
+ i = 0;
+ p = argv[i++];
+ if (!is_empty_arg(p)) {
+ block->file_name = strdup(p);
+ if (block->file_name == NULL) {
+ ERR("not enough memory");
+ return ERR_FATAL;
+ }
+ } else if (block->need_file){
+ ERR("no file specified in %s", arg);
+ return ERR_FATAL;
+ }
+
+ if (block->size_hdr) {
+ p = argv[i++];
+ if (!is_empty_arg(p)) {
+ if (str2u32(p, &block->addr) != 0) {
+ ERR("invalid start address in %s", arg);
+ return ERR_FATAL;
+ }
+ block->addr_set = 1;
+ }
+ }
+
+ p = argv[i++];
+ if (!is_empty_arg(p)) {
+ if (str2u32(p, &block->align) != 0) {
+ ERR("invalid alignment value in %s", arg);
+ return ERR_FATAL;
+ }
+ block->align_set = 1;
+ }
+
+ p = argv[i++];
+ if (!is_empty_arg(p) && (str2u8(p, &block->padc) != 0)) {
+ ERR("invalid paddig character in %s", arg);
+ return ERR_FATAL;
+ }
+
+ num_blocks++;
+
+ return 0;
+}
+
+
+int
+process_blocks(void)
+{
+ struct csys_block *block;
+ uint32_t offs = 0;
+ int i;
+ int res;
+
+ res = 0;
+ /* collecting stats */
+ for (i = 0; i < num_blocks; i++) {
+ block = &blocks[i];
+ res = block_stat_file(block);
+ if (res)
+ return res;
+ }
+
+ /* bootloader */
+ block = boot_block;
+ if (block) {
+ block->size = board->boot_size;
+ if (block->file_size > board->boot_size) {
+ WARN("boot block is too big");
+ res = ERR_INVALID_IMAGE;
+ }
+ }
+ offs += board->boot_size;
+
+ /* configuration data */
+ block = conf_block;
+ if (block) {
+ block->size = board->conf_size;
+ if (block->file_size > board->conf_size) {
+ WARN("config block is too big");
+ res = ERR_INVALID_IMAGE;
+ }
+ }
+ offs += board->conf_size;
+
+ /* webpages */
+ block = webp_block;
+ if (block) {
+
+ memcpy(block->sig, board->sig_webp, 4);
+
+ if (block->addr_set == 0)
+ block->addr = board->addr_webp;
+
+ if (block->align_set == 0)
+ block->align = DEFAULT_BLOCK_ALIGN;
+
+ block->size = align(offs + block->file_size + block->size_hdr +
+ block->size_csum, block->align) - offs;
+
+ if (block->size > board->webp_size_max) {
+ WARN("webpages block is too big");
+ res = ERR_INVALID_IMAGE;
+ }
+
+ DBG(2,"webpages start at %08x, size=%08x", offs,
+ block->size);
+
+ offs += block->size;
+ if (offs > board->flash_size) {
+ WARN("webp block is too big");
+ res = ERR_INVALID_IMAGE;
+ }
+ }
+
+ /* runtime code */
+ block = code_block;
+ if (block) {
+ memcpy(code_block->sig, SIG_CSYS, 4);
+
+ if (block->addr_set == 0)
+ block->addr = board->addr_code;
+
+ if (block->align_set == 0)
+ block->align = DEFAULT_BLOCK_ALIGN;
+
+ block->size = align(offs + block->file_size +
+ block->size_hdr + block->size_csum,
+ block->align) - offs;
+
+ DBG(2,"code block start at %08x, size=%08x", offs,
+ block->size);
+
+ offs += block->size;
+ if (offs > board->flash_size) {
+ WARN("code block is too big");
+ res = ERR_INVALID_IMAGE;
+ }
+ }
+
+ for (i = 0; i < num_blocks; i++) {
+ block = &blocks[i];
+
+ if (block->type != BLOCK_TYPE_XTRA)
+ continue;
+
+ if (block->align_set == 0)
+ block->align = DEFAULT_BLOCK_ALIGN;
+
+ block->size = align(offs + block->file_size,
+ block->align) - offs;
+
+ DBG(2,"file %s start at %08x, size=%08x, align=%08x",
+ block->file_name, offs, block->size, block->align);
+
+ offs += block->size;
+ if (offs > board->flash_size) {
+ WARN("file %s is too big, size=%d, avail=%d",
+ block->file_name, block->file_size,
+ board->flash_size - offs);
+ res = ERR_INVALID_IMAGE;
+ }
+ }
+
+ for (i = 0; i < num_blocks; i++) {
+ block = &blocks[i];
+
+ block->size_avail = block->size - block->size_hdr -
+ block->size_csum;
+
+ if (block->size_avail < block->file_size) {
+ WARN("file %s is too big, size=%d, avail=%d",
+ block->file_name, block->file_size,
+ block->size_avail);
+ res = ERR_INVALID_IMAGE;
+ }
+ }
+
+ return res;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int optinvalid = 0; /* flag for invalid option */
+ int c;
+ int res = ERR_FATAL;
+
+ FILE *outfile;
+
+ progname=basename(argv[0]);
+
+ opterr = 0; /* could not print standard getopt error messages */
+ while ( 1 ) {
+ optinvalid = 0;
+
+ c = getopt(argc, argv, "b:B:c:dhkr:vw:x:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'b':
+ case 'c':
+ case 'r':
+ case 'x':
+ optinvalid = parse_opt_block(c,optarg);
+ break;
+ case 'w':
+ if (optarg != NULL && *optarg == '-') {
+ /* rollback */
+ optind--;
+ optarg = NULL;
+ }
+ optinvalid = parse_opt_block(c,optarg);
+ break;
+ case 'd':
+ invalid_causes_error = 0;
+ break;
+ case 'k':
+ keep_invalid_images = 1;
+ break;
+ case 'B':
+ optinvalid = parse_opt_board(c,optarg);
+ break;
+ case 'v':
+ verblevel++;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ optinvalid = 1;
+ break;
+ }
+ if (optinvalid != 0 ){
+ ERR("invalid option: -%c", optopt);
+ goto out;
+ }
+ }
+
+ if (board == NULL) {
+ ERR("no board specified");
+ goto out;
+ }
+
+ if (optind == argc) {
+ ERR("no output file specified");
+ goto out;
+ }
+
+ ofname = argv[optind++];
+
+ if (optind < argc) {
+ ERR("invalid option: %s", argv[optind]);
+ goto out;
+ }
+
+ res = process_blocks();
+ if (res == ERR_FATAL)
+ goto out;
+
+ if (res == ERR_INVALID_IMAGE) {
+ if (invalid_causes_error)
+ res = ERR_FATAL;
+
+ if (keep_invalid_images == 0) {
+ WARN("generation of invalid images \"%s\" disabled", ofname);
+ goto out;
+ }
+
+ WARN("generating invalid image: \"%s\"", ofname);
+ }
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ res = ERR_FATAL;
+ goto out;
+ }
+
+ if (write_out_blocks(outfile) != 0) {
+ res = ERR_FATAL;
+ goto out_flush;
+ }
+
+ DBG(1,"Image file %s completed.", ofname);
+
+out_flush:
+ fflush(outfile);
+ fclose(outfile);
+ if (res == ERR_FATAL) {
+ unlink(ofname);
+ }
+out:
+ if (res == ERR_FATAL)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/mkdapimg.c b/tools/firmware-utils/src/mkdapimg.c
new file mode 100644
index 0000000..ed662d8
--- /dev/null
+++ b/tools/firmware-utils/src/mkdapimg.c
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+
+#include <netinet/in.h> // htonl
+
+// Usage: mkdapimg [-p] [-m <model>] -s <sig> -i <input> -o <output>
+//
+// e.g.: mkdapimg -s RT3052-AP-DAP1350-3 -i sysupgarde.bin -o factory.bin
+//
+// If the model string <model> is not given, we will assume that
+// the leading characters upto the first "-" is the model.
+//
+// The "-p" (patch) option is used to patch the exisiting image with the
+// specified model and signature.
+// The "-x" (fix) option will recalculate the payload size and checksum
+// during the patch mode operation.
+
+// The img_hdr_struct was taken from the D-Link SDK:
+// DAP-1350_A1_FW1.11NA_GPL/GPL_Source_Code/Uboot/DAP-1350/httpd/header.h
+
+#define MAX_MODEL_NAME_LEN 20
+#define MAX_SIG_LEN 30
+#define MAX_REGION_LEN 4
+#define MAX_VERSION_LEN 12
+
+struct img_hdr_struct {
+ uint32_t checksum;
+ char model[MAX_MODEL_NAME_LEN];
+ char sig[MAX_SIG_LEN];
+ uint8_t partition;
+ uint8_t hdr_len;
+ uint8_t rsv1;
+ uint8_t rsv2;
+ uint32_t flash_byte_cnt;
+} imghdr ;
+
+char *progname;
+
+void
+perrexit(int code, char *msg)
+{
+ fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno));
+ exit(code);
+}
+
+void
+usage()
+{
+ fprintf(stderr, "usage: %s [-p] [-m model] [-r region] [-v version] -s signature -i input -o output\n", progname);
+ exit(1);
+}
+
+int
+main(int ac, char *av[])
+{
+ char model[MAX_MODEL_NAME_LEN+1];
+ char signature[MAX_SIG_LEN+1];
+ char region[MAX_REGION_LEN+1];
+ char version[MAX_VERSION_LEN+1];
+ int patchmode = 0;
+ int fixmode = 0;
+ int have_regionversion = 0;
+
+ FILE *ifile, *ofile;
+ int c;
+ uint32_t cksum;
+ uint32_t bcnt;
+
+ progname = basename(av[0]);
+ memset(model, 0, sizeof(model));
+ memset(signature, 0, sizeof(signature));
+ memset(region, 0, sizeof(region));
+ memset(version, 0, sizeof(version));
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(ac, av, "pxm:r:v:s:i:o:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'p':
+ patchmode = 1;
+ break;
+ case 'x':
+ fixmode = 1;
+ break;
+ case 'm':
+ if (strlen(optarg) > MAX_MODEL_NAME_LEN) {
+ fprintf(stderr, "%s: model name exceeds %d chars\n",
+ progname, MAX_MODEL_NAME_LEN);
+ exit(1);
+ }
+ strcpy(model, optarg);
+ break;
+ case 'r':
+ if (strlen(optarg) > MAX_REGION_LEN) {
+ fprintf(stderr, "%s: region exceeds %d chars\n",
+ progname, MAX_REGION_LEN);
+ exit(1);
+ }
+ have_regionversion = 1;
+ strcpy(region, optarg);
+ break;
+ case 'v':
+ if (strlen(optarg) > MAX_VERSION_LEN) {
+ fprintf(stderr, "%s: version exceeds %d chars\n",
+ progname, MAX_VERSION_LEN);
+ exit(1);
+ }
+ have_regionversion = 1;
+ strcpy(version, optarg);
+ break;
+ case 's':
+ if (strlen(optarg) > MAX_SIG_LEN) {
+ fprintf(stderr, "%s: signature exceeds %d chars\n",
+ progname, MAX_SIG_LEN);
+ exit(1);
+ }
+ strcpy(signature, optarg);
+ break;
+ case 'i':
+ if ((ifile = fopen(optarg, "r")) == NULL)
+ perrexit(1, optarg);
+ break;
+ case 'o':
+ if ((ofile = fopen(optarg, "w")) == NULL)
+ perrexit(1, optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (signature[0] == 0 || ifile == NULL || ofile == NULL) {
+ usage();
+ }
+
+ if (model[0] == 0) {
+ char *p = strchr(signature, '-');
+ if (p == NULL) {
+ fprintf(stderr, "%s: model name unknown\n", progname);
+ exit(1);
+ }
+ if (p - signature > MAX_MODEL_NAME_LEN) {
+ *p = 0;
+ fprintf(stderr, "%s: auto model name failed, string %s too long\n", progname, signature);
+ exit(1);
+ }
+ strncpy(model, signature, p - signature);
+ }
+
+ if (patchmode) {
+ if (fread(&imghdr, sizeof(imghdr), 1, ifile) < 0)
+ perrexit(2, "fread on input");
+ }
+
+ for (bcnt = 0, cksum = 0 ; (c = fgetc(ifile)) != EOF ; bcnt++)
+ cksum += c & 0xff;
+
+ if (fseek(ifile, patchmode ? sizeof(imghdr) : 0, SEEK_SET) < 0)
+ perrexit(2, "fseek on input");
+
+ if (patchmode == 0) {
+ // Fill in the header
+ memset(&imghdr, 0, sizeof(imghdr));
+ imghdr.checksum = htonl(cksum);
+ imghdr.partition = 0 ; // don't care?
+ imghdr.hdr_len = sizeof(imghdr);
+ if (have_regionversion) {
+ imghdr.hdr_len += MAX_REGION_LEN;
+ imghdr.hdr_len += MAX_VERSION_LEN;
+ }
+ imghdr.flash_byte_cnt = htonl(bcnt);
+ } else {
+ if (ntohl(imghdr.checksum) != cksum) {
+ fprintf(stderr, "%s: patch mode, checksum mismatch\n",
+ progname);
+ if (fixmode) {
+ fprintf(stderr, "%s: fixing\n", progname);
+ imghdr.checksum = htonl(cksum);
+ } else
+ exit(3);
+ } else if (ntohl(imghdr.flash_byte_cnt) != bcnt) {
+ fprintf(stderr, "%s: patch mode, size mismatch\n",
+ progname);
+ if (fixmode) {
+ fprintf(stderr, "%s: fixing\n", progname);
+ imghdr.flash_byte_cnt = htonl(bcnt);
+ } else
+ exit(3);
+ }
+ }
+
+ strncpy(imghdr.model, model, MAX_MODEL_NAME_LEN);
+ strncpy(imghdr.sig, signature, MAX_SIG_LEN);
+
+ if (fwrite(&imghdr, sizeof(imghdr), 1, ofile) < 0)
+ perrexit(2, "fwrite header on output");
+ if (have_regionversion) {
+ if (fwrite(&region, MAX_REGION_LEN, 1, ofile) < 0)
+ perrexit(2, "fwrite header on output");
+ if (fwrite(&version, MAX_VERSION_LEN, 1, ofile) < 0)
+ perrexit(2, "fwrite header on output");
+ }
+
+ while ((c = fgetc(ifile)) != EOF) {
+ if (fputc(c, ofile) == EOF)
+ perrexit(2, "fputc on output");
+ }
+
+ if (ferror(ifile))
+ perrexit(2, "fgetc on input");
+
+
+ fclose(ofile);
+ fclose(ifile);
+}
diff --git a/tools/firmware-utils/src/mkdcs932.c b/tools/firmware-utils/src/mkdcs932.c
new file mode 100644
index 0000000..28c67aa
--- /dev/null
+++ b/tools/firmware-utils/src/mkdcs932.c
@@ -0,0 +1,39 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2 as published by the Free Software Foundation.
+ *
+ * (C) John Crispin <blogic@openwrt.org>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+
+int main(int argc, char **argv)
+{
+ uint32_t t = 0, sum = 0x55aa55aa;
+ int fd;
+
+ if ((argc != 2) || ((fd = open(argv[1], O_RDWR)) == -1)) {
+ fprintf(stderr, "Usage: %s input_file\n", *argv);
+ return -EINVAL;
+ }
+
+ lseek(fd, -4, SEEK_END);
+ write(fd, &t, 4);
+ lseek(fd, 0, SEEK_SET);
+
+ while (read(fd, &t, 4) > 0)
+ sum -= t;
+
+ lseek(fd, -4, SEEK_END);
+ write(fd, &sum, 4);
+ close(fd);
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/mkdniimg.c b/tools/firmware-utils/src/mkdniimg.c
new file mode 100644
index 0000000..852b07d
--- /dev/null
+++ b/tools/firmware-utils/src/mkdniimg.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#define DNI_HDR_LEN 128
+
+/*
+ * Globals
+ */
+static char *ifname;
+static char *progname;
+static char *ofname;
+static char *version = "1.00.00";
+static char *region = "";
+static char *hd_id;
+
+static char *board_id;
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>\n"
+" -i <file> read input from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -v <version> set image version to <version>\n"
+" -r <region> set image region to <region>\n"
+" -H <hd_id> set image hardware id to <hd_id>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+ int res = EXIT_FAILURE;
+ int buflen;
+ int err;
+ struct stat st;
+ char *buf;
+ int pos, rem, i;
+ uint8_t csum;
+
+ FILE *outfile, *infile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "B:i:o:v:r:H:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'B':
+ board_id = optarg;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'v':
+ version = optarg;
+ break;
+ case 'r':
+ region = optarg;
+ break;
+ case 'H':
+ hd_id = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (board_id == NULL) {
+ ERR("no board specified");
+ goto err;
+ }
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto err;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto err;
+ }
+
+ err = stat(ifname, &st);
+ if (err){
+ ERRS("stat failed on %s", ifname);
+ goto err;
+ }
+
+ buflen = st.st_size + DNI_HDR_LEN + 1;
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto err;
+ }
+
+ memset(buf, 0, DNI_HDR_LEN);
+ pos = snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:V%s\nregion:%s\n",
+ board_id, version, region);
+ rem = DNI_HDR_LEN - pos;
+ if (pos >= 0 && rem > 1 && hd_id) {
+ snprintf(buf + pos, rem, "hd_id:%s\n", hd_id);
+ }
+
+ infile = fopen(ifname, "r");
+ if (infile == NULL) {
+ ERRS("could not open \"%s\" for reading", ifname);
+ goto err_free;
+ }
+
+ errno = 0;
+ fread(buf + DNI_HDR_LEN, st.st_size, 1, infile);
+ if (errno != 0) {
+ ERRS("unable to read from file %s", ifname);
+ goto err_close_in;
+ }
+
+ csum = 0;
+ for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++)
+ csum += buf[i];
+
+ csum = 0xff - csum;
+ buf[st.st_size + DNI_HDR_LEN] = csum;
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto err_close_in;
+ }
+
+ errno = 0;
+ fwrite(buf, buflen, 1, outfile);
+ if (errno) {
+ ERRS("unable to write to file %s", ofname);
+ goto err_close_out;
+ }
+
+ res = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(outfile);
+
+ err_close_out:
+ fclose(outfile);
+ if (res != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+
+ err_close_in:
+ fclose(infile);
+
+ err_free:
+ free(buf);
+
+ err:
+ return res;
+}
diff --git a/tools/firmware-utils/src/mkedimaximg.c b/tools/firmware-utils/src/mkedimaximg.c
new file mode 100644
index 0000000..d8a017e
--- /dev/null
+++ b/tools/firmware-utils/src/mkedimaximg.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2011 Vasilis Tsiligiannis <b_tsiligiannis@silverton.gr>
+ *
+ * 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <endian.h> /* for __BYTE_ORDER */
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define HOST_TO_LE16(x) (x)
+# define HOST_TO_LE32(x) (x)
+#else
+# define HOST_TO_LE16(x) bswap_16(x)
+# define HOST_TO_LE32(x) bswap_32(x)
+#endif
+
+struct header
+{
+ unsigned char sign[4];
+ unsigned int start;
+ unsigned int flash;
+ unsigned char model[4];
+ unsigned int size;
+} __attribute__ ((packed));
+
+struct finfo
+{
+ char *name;
+ off_t size;
+};
+
+struct buf
+{
+ char *start;
+ size_t size;
+};
+
+static char *progname;
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+ "\n"
+ "Options:\n"
+ " -s <sig> set image signature to <sig>\n"
+ " -m <model> set model to <model>\n"
+ " -i <file> read input from file <file>\n"
+ " -o <file> write output to file <file>\n"
+ " -f <flash> set flash address to <flash>\n"
+ " -S <start> set start address to <start>\n");
+
+ exit(status);
+}
+
+static int strtou32(char *arg, unsigned int *val)
+{
+ char *endptr = NULL;
+
+ errno = 0;
+ *val = strtoul(arg, &endptr, 0);
+ if (errno || (endptr == arg) || (*endptr && (endptr != NULL))) {
+ return EXIT_SUCCESS;
+ }
+
+ return EXIT_FAILURE;
+}
+
+static unsigned short fwcsum (struct buf *buf) {
+ int i;
+ unsigned short ret = 0;
+
+ for (i = 0; i < buf->size / 2; i++)
+ ret -= ((unsigned short *) buf->start)[i];
+
+ return ret;
+}
+
+static int fwread(struct finfo *finfo, struct buf *buf)
+{
+ FILE *f;
+
+ f = fopen(finfo->name, "r");
+ if (!f) {
+ fprintf(stderr, "could not open \"%s\" for reading\n", finfo->name);
+ usage(EXIT_FAILURE);
+ }
+
+ buf->size = fread(buf->start, 1, finfo->size, f);
+ if (buf->size != finfo->size) {
+ fprintf(stderr, "unable to read from file \"%s\"\n", finfo->name);
+ usage(EXIT_FAILURE);
+ }
+
+ fclose(f);
+
+ return EXIT_SUCCESS;
+}
+
+static int fwwrite(struct finfo *finfo, struct buf *buf)
+{
+ FILE *f;
+
+ f = fopen(finfo->name, "w");
+ if (!f) {
+ fprintf(stderr, "could not open \"%s\" for writing\n", finfo->name);
+ usage(EXIT_FAILURE);
+ }
+
+ buf->size = fwrite(buf->start, 1, finfo->size, f);
+ if (buf->size != finfo->size) {
+ fprintf(stderr, "unable to write to file \"%s\"\n", finfo->name);
+ usage(EXIT_FAILURE);
+ }
+
+ fclose(f);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+ struct stat st;
+ struct header header;
+ struct buf ibuf, obuf;
+ struct finfo ifinfo, ofinfo;
+ unsigned short csum;
+ int c;
+
+ ifinfo.name = ofinfo.name = NULL;
+ header.flash = header.size = header.start = 0;
+ progname = basename(argv[0]);
+
+ while((c = getopt(argc, argv, "i:o:m:s:f:S:h")) != -1) {
+ switch (c) {
+ case 'i':
+ ifinfo.name = optarg;
+ break;
+ case 'o':
+ ofinfo.name = optarg;
+ break;
+ case 'm':
+ if (strlen(optarg) != 4) {
+ fprintf(stderr, "model must be 4 characters long\n");
+ usage(EXIT_FAILURE);
+ }
+ memcpy(header.model, optarg, 4);
+ break;
+ case 's':
+ if (strlen(optarg) != 4) {
+ fprintf(stderr, "signature must be 4 characters long\n");
+ usage(EXIT_FAILURE);
+ }
+ memcpy(header.sign, optarg, 4);
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ case 'f':
+ if (!strtou32(optarg, &header.flash)) {
+ fprintf(stderr, "invalid flash address specified\n");
+ usage(EXIT_FAILURE);
+ }
+ break;
+ case 'S':
+ if (!strtou32(optarg, &header.start)) {
+ fprintf(stderr, "invalid start address specified\n");
+ usage(EXIT_FAILURE);
+ }
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (ifinfo.name == NULL) {
+ fprintf(stderr, "no input file specified\n");
+ usage(EXIT_FAILURE);
+ }
+
+ if (ofinfo.name == NULL) {
+ fprintf(stderr, "no output file specified\n");
+ usage(EXIT_FAILURE);
+ }
+
+ if (stat(ifinfo.name, &st)) {
+ fprintf(stderr, "stat failed on %s\n", ifinfo.name);
+ usage(EXIT_FAILURE);
+ }
+
+ if (header.sign == NULL) {
+ fprintf(stderr, "no signature specified\n");
+ usage(EXIT_FAILURE);
+ }
+
+ if (header.model == NULL) {
+ fprintf(stderr, "no model specified\n");
+ usage(EXIT_FAILURE);
+ }
+
+ if (!header.flash) {
+ fprintf(stderr, "no flash address specified\n");
+ usage(EXIT_FAILURE);
+ }
+
+ if (!header.start) {
+ fprintf(stderr, "no start address specified\n");
+ usage(EXIT_FAILURE);
+ }
+
+ ifinfo.size = st.st_size;
+
+ obuf.size = ifinfo.size + sizeof(struct header) + sizeof(unsigned short);
+ if (obuf.size % sizeof(unsigned short))
+ obuf.size++;
+
+ obuf.start = malloc(obuf.size);
+ if (!obuf.start) {
+ fprintf(stderr, "no memory for buffer\n");
+ usage(EXIT_FAILURE);
+ }
+ memset(obuf.start, 0, obuf.size);
+
+ ibuf.size = ifinfo.size;
+ ibuf.start = obuf.start + sizeof(struct header);
+
+ if (fwread(&ifinfo, &ibuf))
+ usage(EXIT_FAILURE);
+
+ header.flash = HOST_TO_LE32(header.flash);
+ header.size = HOST_TO_LE32(obuf.size - sizeof(struct header));
+ header.start = HOST_TO_LE32(header.start);
+ memcpy (obuf.start, &header, sizeof(struct header));
+
+ csum = HOST_TO_LE16(fwcsum(&ibuf));
+ memcpy(obuf.start + obuf.size - sizeof(unsigned short),
+ &csum, sizeof(unsigned short));
+
+ ofinfo.size = obuf.size;
+
+ if (fwwrite(&ofinfo, &obuf))
+ usage(EXIT_FAILURE);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/mkfwimage.c b/tools/firmware-utils/src/mkfwimage.c
new file mode 100644
index 0000000..e3a03c1
--- /dev/null
+++ b/tools/firmware-utils/src/mkfwimage.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2007 Ubiquiti Networks, Inc.
+ * Copyright (C) 2008 Lukas Kuna <ValXdater@seznam.cz>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <zlib.h>
+#include <sys/mman.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "fw.h"
+
+typedef struct fw_layout_data {
+ char name[PATH_MAX];
+ u_int32_t kern_start;
+ u_int32_t kern_entry;
+ u_int32_t firmware_max_length;
+} fw_layout_t;
+
+fw_layout_t fw_layout_data[] = {
+ {
+ .name = "XS2",
+ .kern_start = 0xbfc30000,
+ .kern_entry = 0x80041000,
+ .firmware_max_length= 0x00390000,
+ },
+ {
+ .name = "XS5",
+ .kern_start = 0xbe030000,
+ .kern_entry = 0x80041000,
+ .firmware_max_length= 0x00390000,
+ },
+ {
+ .name = "RS",
+ .kern_start = 0xbf030000,
+ .kern_entry = 0x80060000,
+ .firmware_max_length= 0x00B00000,
+ },
+ {
+ .name = "RSPRO",
+ .kern_start = 0xbf030000,
+ .kern_entry = 0x80060000,
+ .firmware_max_length= 0x00F00000,
+ },
+ {
+ .name = "LS-SR71",
+ .kern_start = 0xbf030000,
+ .kern_entry = 0x80060000,
+ .firmware_max_length= 0x00640000,
+ },
+ {
+ .name = "XS2-8",
+ .kern_start = 0xa8030000,
+ .kern_entry = 0x80041000,
+ .firmware_max_length= 0x006C0000,
+ },
+ {
+ .name = "XM",
+ .kern_start = 0x9f050000,
+ .kern_entry = 0x80002000,
+ .firmware_max_length= 0x006A0000,
+ },
+ { .name = "",
+ },
+};
+
+typedef struct part_data {
+ char partition_name[64];
+ int partition_index;
+ u_int32_t partition_baseaddr;
+ u_int32_t partition_startaddr;
+ u_int32_t partition_memaddr;
+ u_int32_t partition_entryaddr;
+ u_int32_t partition_length;
+
+ char filename[PATH_MAX];
+ struct stat stats;
+} part_data_t;
+
+#define MAX_SECTIONS 8
+#define DEFAULT_OUTPUT_FILE "firmware-image.bin"
+#define DEFAULT_VERSION "UNKNOWN"
+
+#define OPTIONS "B:hv:m:o:r:k:"
+
+static int debug = 0;
+
+typedef struct image_info {
+ char magic[16];
+ char version[256];
+ char outputfile[PATH_MAX];
+ u_int32_t part_count;
+ part_data_t parts[MAX_SECTIONS];
+} image_info_t;
+
+static void write_header(void* mem, const char *magic, const char* version)
+{
+ header_t* header = mem;
+ memset(header, 0, sizeof(header_t));
+
+ memcpy(header->magic, magic, MAGIC_LENGTH);
+ strncpy(header->version, version, sizeof(header->version));
+ header->crc = htonl(crc32(0L, (unsigned char *)header,
+ sizeof(header_t) - 2 * sizeof(u_int32_t)));
+ header->pad = 0L;
+}
+
+
+static void write_signature(void* mem, u_int32_t sig_offset)
+{
+ /* write signature */
+ signature_t* sign = (signature_t*)(mem + sig_offset);
+ memset(sign, 0, sizeof(signature_t));
+
+ memcpy(sign->magic, MAGIC_END, MAGIC_LENGTH);
+ sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset));
+ sign->pad = 0L;
+}
+
+static int write_part(void* mem, part_data_t* d)
+{
+ char* addr;
+ int fd;
+ part_t* p = mem;
+ part_crc_t* crc = mem + sizeof(part_t) + d->stats.st_size;
+
+ fd = open(d->filename, O_RDONLY);
+ if (fd < 0)
+ {
+ ERROR("Failed opening file '%s'\n", d->filename);
+ return -1;
+ }
+
+ if ((addr=(char*)mmap(0, d->stats.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
+ {
+ ERROR("Failed mmaping memory for file '%s'\n", d->filename);
+ close(fd);
+ return -2;
+ }
+
+ memcpy(mem + sizeof(part_t), addr, d->stats.st_size);
+ munmap(addr, d->stats.st_size);
+
+ memset(p->name, 0, sizeof(p->name));
+ strncpy(p->magic, MAGIC_PART, MAGIC_LENGTH);
+ strncpy(p->name, d->partition_name, sizeof(p->name));
+ p->index = htonl(d->partition_index);
+ p->data_size = htonl(d->stats.st_size);
+ p->part_size = htonl(d->partition_length);
+ p->baseaddr = htonl(d->partition_baseaddr);
+ p->memaddr = htonl(d->partition_memaddr);
+ p->entryaddr = htonl(d->partition_entryaddr);
+
+ crc->crc = htonl(crc32(0L, mem, d->stats.st_size + sizeof(part_t)));
+ crc->pad = 0L;
+
+ return 0;
+}
+
+static void usage(const char* progname)
+{
+ INFO("Version %s\n"
+ "Usage: %s [options]\n"
+ "\t-v <version string>\t - firmware version information, default: %s\n"
+ "\t-o <output file>\t - firmware output file, default: %s\n"
+ "\t-m <magic>\t - firmware magic, default: %s\n"
+ "\t-k <kernel file>\t\t - kernel file\n"
+ "\t-r <rootfs file>\t\t - rootfs file\n"
+ "\t-B <board name>\t\t - choose firmware layout for specified board (XS2, XS5, RS, XM)\n"
+ "\t-h\t\t\t - this help\n", VERSION,
+ progname, DEFAULT_VERSION, DEFAULT_OUTPUT_FILE, MAGIC_HEADER);
+}
+
+static void print_image_info(const image_info_t* im)
+{
+ int i = 0;
+ INFO("Firmware version: '%s'\n"
+ "Output file: '%s'\n"
+ "Part count: %u\n",
+ im->version, im->outputfile,
+ im->part_count);
+
+ for (i = 0; i < im->part_count; ++i)
+ {
+ const part_data_t* d = &im->parts[i];
+ INFO(" %10s: %8ld bytes (free: %8ld)\n",
+ d->partition_name,
+ d->stats.st_size,
+ d->partition_length - d->stats.st_size);
+ }
+}
+
+
+
+static u_int32_t filelength(const char* file)
+{
+ FILE *p;
+ int ret = -1;
+
+ if ( (p = fopen(file, "rb") ) == NULL) return (-1);
+
+ fseek(p, 0, SEEK_END);
+ ret = ftell(p);
+
+ fclose (p);
+
+ return (ret);
+}
+
+static int create_image_layout(const char* kernelfile, const char* rootfsfile, char* board_name, image_info_t* im)
+{
+ part_data_t* kernel = &im->parts[0];
+ part_data_t* rootfs = &im->parts[1];
+
+ fw_layout_t* p;
+
+ p = &fw_layout_data[0];
+ while ((strlen(p->name) != 0) && (strncmp(p->name, board_name, sizeof(board_name)) != 0))
+ p++;
+ if (p->name == NULL) {
+ printf("BUG! Unable to find default fw layout!\n");
+ exit(-1);
+ }
+
+ printf("board = %s\n", p->name);
+ strcpy(kernel->partition_name, "kernel");
+ kernel->partition_index = 1;
+ kernel->partition_baseaddr = p->kern_start;
+ if ( (kernel->partition_length = filelength(kernelfile)) < 0) return (-1);
+ kernel->partition_memaddr = p->kern_entry;
+ kernel->partition_entryaddr = p->kern_entry;
+ strncpy(kernel->filename, kernelfile, sizeof(kernel->filename));
+
+ if (filelength(rootfsfile) + kernel->partition_length > p->firmware_max_length)
+ return (-2);
+
+ strcpy(rootfs->partition_name, "rootfs");
+ rootfs->partition_index = 2;
+ rootfs->partition_baseaddr = kernel->partition_baseaddr + kernel->partition_length;
+ rootfs->partition_length = p->firmware_max_length - kernel->partition_length;
+ rootfs->partition_memaddr = 0x00000000;
+ rootfs->partition_entryaddr = 0x00000000;
+ strncpy(rootfs->filename, rootfsfile, sizeof(rootfs->filename));
+
+printf("kernel: %d 0x%08x\n", kernel->partition_length, kernel->partition_baseaddr);
+printf("root: %d 0x%08x\n", rootfs->partition_length, rootfs->partition_baseaddr);
+ im->part_count = 2;
+
+ return 0;
+}
+
+/**
+ * Checks the availability and validity of all image components.
+ * Fills in stats member of the part_data structure.
+ */
+static int validate_image_layout(image_info_t* im)
+{
+ int i;
+
+ if (im->part_count == 0 || im->part_count > MAX_SECTIONS)
+ {
+ ERROR("Invalid part count '%d'\n", im->part_count);
+ return -1;
+ }
+
+ for (i = 0; i < im->part_count; ++i)
+ {
+ part_data_t* d = &im->parts[i];
+ int len = strlen(d->partition_name);
+ if (len == 0 || len > 16)
+ {
+ ERROR("Invalid partition name '%s' of the part %d\n",
+ d->partition_name, i);
+ return -1;
+ }
+ if (stat(d->filename, &d->stats) < 0)
+ {
+ ERROR("Couldn't stat file '%s' from part '%s'\n",
+ d->filename, d->partition_name);
+ return -2;
+ }
+ if (d->stats.st_size == 0)
+ {
+ ERROR("File '%s' from part '%s' is empty!\n",
+ d->filename, d->partition_name);
+ return -3;
+ }
+ if (d->stats.st_size > d->partition_length) {
+ ERROR("File '%s' too big (%d) - max size: 0x%08X (exceeds %lu bytes)\n",
+ d->filename, i, d->partition_length,
+ d->stats.st_size - d->partition_length);
+ return -4;
+ }
+ }
+
+ return 0;
+}
+
+static int build_image(image_info_t* im)
+{
+ char* mem;
+ char* ptr;
+ u_int32_t mem_size;
+ FILE* f;
+ int i;
+
+ // build in-memory buffer
+ mem_size = sizeof(header_t) + sizeof(signature_t);
+ for (i = 0; i < im->part_count; ++i)
+ {
+ part_data_t* d = &im->parts[i];
+ mem_size += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);
+ }
+
+ mem = (char*)calloc(mem_size, 1);
+ if (mem == NULL)
+ {
+ ERROR("Cannot allocate memory chunk of size '%u'\n", mem_size);
+ return -1;
+ }
+
+ // write header
+ write_header(mem, im->magic, im->version);
+ ptr = mem + sizeof(header_t);
+ // write all parts
+ for (i = 0; i < im->part_count; ++i)
+ {
+ part_data_t* d = &im->parts[i];
+ int rc;
+ if ((rc = write_part(ptr, d)) != 0)
+ {
+ ERROR("ERROR: failed writing part %u '%s'\n", i, d->partition_name);
+ }
+ ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);
+ }
+ // write signature
+ write_signature(mem, mem_size - sizeof(signature_t));
+
+ // write in-memory buffer into file
+ if ((f = fopen(im->outputfile, "w")) == NULL)
+ {
+ ERROR("Can not create output file: '%s'\n", im->outputfile);
+ return -10;
+ }
+
+ if (fwrite(mem, mem_size, 1, f) != 1)
+ {
+ ERROR("Could not write %d bytes into file: '%s'\n",
+ mem_size, im->outputfile);
+ return -11;
+ }
+
+ free(mem);
+ fclose(f);
+ return 0;
+}
+
+
+int main(int argc, char* argv[])
+{
+ char kernelfile[PATH_MAX];
+ char rootfsfile[PATH_MAX];
+ char board_name[PATH_MAX];
+ int o, rc;
+ image_info_t im;
+
+ memset(&im, 0, sizeof(im));
+ memset(kernelfile, 0, sizeof(kernelfile));
+ memset(rootfsfile, 0, sizeof(rootfsfile));
+ memset(board_name, 0, sizeof(board_name));
+
+ strcpy(im.outputfile, DEFAULT_OUTPUT_FILE);
+ strcpy(im.version, DEFAULT_VERSION);
+ strncpy(im.magic, MAGIC_HEADER, sizeof(im.magic));
+
+ while ((o = getopt(argc, argv, OPTIONS)) != -1)
+ {
+ switch (o) {
+ case 'v':
+ if (optarg)
+ strncpy(im.version, optarg, sizeof(im.version));
+ break;
+ case 'o':
+ if (optarg)
+ strncpy(im.outputfile, optarg, sizeof(im.outputfile));
+ break;
+ case 'm':
+ if (optarg)
+ strncpy(im.magic, optarg, sizeof(im.magic));
+ break;
+ case 'h':
+ usage(argv[0]);
+ return -1;
+ case 'k':
+ if (optarg)
+ strncpy(kernelfile, optarg, sizeof(kernelfile));
+ break;
+ case 'r':
+ if (optarg)
+ strncpy(rootfsfile, optarg, sizeof(rootfsfile));
+ break;
+ case 'B':
+ if (optarg)
+ strncpy(board_name, optarg, sizeof(board_name));
+ break;
+ }
+ }
+ if (strlen(board_name) == 0)
+ strcpy(board_name, "XS2"); /* default to XS2 */
+
+ if (strlen(kernelfile) == 0)
+ {
+ ERROR("Kernel file is not specified, cannot continue\n");
+ usage(argv[0]);
+ return -2;
+ }
+
+ if (strlen(rootfsfile) == 0)
+ {
+ ERROR("Root FS file is not specified, cannot continue\n");
+ usage(argv[0]);
+ return -2;
+ }
+
+ if ((rc = create_image_layout(kernelfile, rootfsfile, board_name, &im)) != 0)
+ {
+ ERROR("Failed creating firmware layout description - error code: %d\n", rc);
+ return -3;
+ }
+
+ if ((rc = validate_image_layout(&im)) != 0)
+ {
+ ERROR("Failed validating firmware layout - error code: %d\n", rc);
+ return -4;
+ }
+
+ print_image_info(&im);
+
+ if ((rc = build_image(&im)) != 0)
+ {
+ ERROR("Failed building image file '%s' - error code: %d\n", im.outputfile, rc);
+ return -5;
+ }
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/mkfwimage2.c b/tools/firmware-utils/src/mkfwimage2.c
new file mode 100644
index 0000000..993c3d4
--- /dev/null
+++ b/tools/firmware-utils/src/mkfwimage2.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2007 Ubiquiti Networks, Inc.
+ * Copyright (C) 2008 Lukas Kuna <ValXdater@seznam.cz>
+ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <zlib.h>
+#include <sys/mman.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "fw.h"
+
+#undef VERSION
+#define VERSION "1.2-OpenWrt.1"
+
+#define MAX_SECTIONS 8
+#define DEFAULT_OUTPUT_FILE "firmware-image.bin"
+#define DEFAULT_VERSION "UNKNOWN"
+#define DEFAULT_FLASH_BASE (0xbfc00000)
+
+#define FIRMWARE_MAX_LENGTH (0x390000)
+
+typedef struct part_data {
+ char partition_name[64];
+ int partition_index;
+ u_int32_t partition_baseaddr;
+ u_int32_t partition_offset;
+ u_int32_t partition_memaddr;
+ u_int32_t partition_entryaddr;
+ u_int32_t partition_length;
+
+ char filename[PATH_MAX];
+ struct stat stats;
+} part_data_t;
+
+typedef struct image_info {
+ char version[256];
+ char outputfile[PATH_MAX];
+ char magic[MAGIC_LENGTH];
+ u_int32_t flash_baseaddr;
+ u_int32_t part_count;
+ part_data_t parts[MAX_SECTIONS];
+} image_info_t;
+
+static image_info_t im;
+static int debug = 0;
+static int zero_part_baseaddr = 0;
+
+static void write_header(void* mem, const char* version)
+{
+ header_t* header = mem;
+ memset(header, 0, sizeof(header_t));
+
+ memcpy(header->magic, im.magic, MAGIC_LENGTH);
+ strncpy(header->version, version, sizeof(header->version));
+ header->crc = htonl(crc32(0L, (unsigned char *)header,
+ sizeof(header_t) - 2 * sizeof(u_int32_t)));
+ header->pad = 0L;
+}
+
+static void write_signature(void* mem, u_int32_t sig_offset)
+{
+ /* write signature */
+ signature_t* sign = (signature_t*)(mem + sig_offset);
+ memset(sign, 0, sizeof(signature_t));
+
+ memcpy(sign->magic, MAGIC_END, MAGIC_LENGTH);
+ sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset));
+ sign->pad = 0L;
+}
+
+static int write_part(void* mem, part_data_t* d)
+{
+ char* addr;
+ int fd;
+ part_t* p = mem;
+ part_crc_t* crc = mem + sizeof(part_t) + d->stats.st_size;
+
+ fd = open(d->filename, O_RDONLY);
+ if (fd < 0) {
+ ERROR("Failed opening file '%s'\n", d->filename);
+ return -1;
+ }
+
+ if ((addr=(char*)mmap(0, d->stats.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+ ERROR("Failed mmaping memory for file '%s'\n", d->filename);
+ close(fd);
+ return -2;
+ }
+
+ memcpy(mem + sizeof(part_t), addr, d->stats.st_size);
+ munmap(addr, d->stats.st_size);
+
+ memset(p->name, 0, sizeof(p->name));
+ strncpy(p->magic, MAGIC_PART, MAGIC_LENGTH);
+ strncpy(p->name, d->partition_name, sizeof(p->name));
+ p->index = htonl(d->partition_index);
+ p->data_size = htonl(d->stats.st_size);
+ p->part_size = htonl(d->partition_length);
+ p->baseaddr = htonl(d->partition_baseaddr);
+ p->memaddr = htonl(d->partition_memaddr);
+ p->entryaddr = htonl(d->partition_entryaddr);
+
+ crc->crc = htonl(crc32(0L, mem, d->stats.st_size + sizeof(part_t)));
+ crc->pad = 0L;
+
+ return 0;
+}
+
+static void usage(const char* progname)
+{
+ INFO("Version %s\n"
+ "Usage: %s [options]\n"
+ "\t-v <version string>\t - firmware version information, default: %s\n"
+ "\t-m <magic>\t\t - firmware magic, default: %s\n"
+ "\t-f <flash base>\t\t - flash base address, default: 0x%08x\n"
+ "\t-o <output file>\t - firmware output file, default: %s\n"
+ "\t-p <name>:<offset>:<len>:<memaddr>:<entry>:<file>\n "
+ "\t\t\t\t - create a partition from <file>\n"
+ "\t-z\t\t\t - set partition offsets to zero\n"
+ "\t-h\t\t\t - this help\n",
+ VERSION, progname, DEFAULT_VERSION, MAGIC_HEADER,
+ DEFAULT_FLASH_BASE, DEFAULT_OUTPUT_FILE);
+}
+
+static void print_image_info(void)
+{
+ int i;
+
+ INFO("Firmware version : '%s'\n"
+ "Output file : '%s'\n"
+ "Part count : %u\n",
+ im.version, im.outputfile, im.part_count);
+
+ for (i = 0; i < im.part_count; ++i) {
+ const part_data_t* d = &im.parts[i];
+ INFO(" %10s: %08x %08x %08x %08x %8ld bytes (free: %8ld)\n",
+ d->partition_name,
+ d->partition_baseaddr,
+ d->partition_length,
+ d->partition_entryaddr,
+ d->partition_memaddr,
+ d->stats.st_size,
+ d->partition_length - d->stats.st_size);
+ }
+}
+
+static int filelength(const char* file)
+{
+ FILE *p;
+ int ret = -1;
+
+ if ( (p = fopen(file, "rb") ) == NULL) return (-1);
+
+ fseek(p, 0, SEEK_END);
+ ret = ftell(p);
+
+ fclose (p);
+
+ return (ret);
+}
+
+int str2u32(char *arg, u_int32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno = 0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err == arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+static int image_layout_add_partition(const char *part_desc)
+{
+ part_data_t *d;
+ char memaddr[16];
+ char entryaddr[16];
+ char offset[16];
+ char length[16];
+ int t;
+
+ if (im.part_count >= MAX_SECTIONS) {
+ ERROR("Too many partitions specified\n");
+ return (-1);
+ }
+
+ d = &im.parts[im.part_count];
+ t = sscanf(part_desc, "%15[0-9a-zA-Z]:%15[0-9a-fA-Fx]:%15[0-9a-fA-Fx]:%15[0-9a-fA-Fx]:%15[0-9a-fA-Fx]:%256s",
+ d->partition_name,
+ offset,
+ length,
+ memaddr,
+ entryaddr,
+ d->filename);
+
+ if (t != 6) {
+ ERROR("Bad partition parameter %d, '%s'\n", t, part_desc);
+ return (-1);
+ }
+
+ if (strlen(d->partition_name) == 0) {
+ ERROR("No partition name specified in '%s'\n", part_desc);
+ return (-1);
+ }
+
+ if (str2u32(offset, &d->partition_offset)) {
+ ERROR("Bad offset value '%s'\n", offset);
+ return (-1);
+ }
+
+ if (str2u32(length, &d->partition_length)) {
+ ERROR("Bad length value '%s'\n", length);
+ return (-1);
+ }
+
+ if (d->partition_length == 0) {
+ int flen;
+ flen = filelength(d->filename);
+ if (flen < 0) {
+ ERROR("Unable to determine size of '%s'\n",
+ d->filename);
+ return (-1);
+ }
+ d->partition_length = flen;
+ }
+
+ if (str2u32(memaddr, &d->partition_memaddr)) {
+ ERROR("Bad memaddr vaule '%s'\n", memaddr);
+ return (-1);
+ }
+
+ if (str2u32(entryaddr, &d->partition_entryaddr)) {
+ ERROR("Bad entry address value '%s'\n", entryaddr);
+ return (-1);
+ }
+
+ im.part_count++;
+ d->partition_index = im.part_count;
+
+ return 0;
+}
+
+static int image_layout_verify(void)
+{
+ u_int32_t offset;
+ int i;
+
+ if (im.part_count == 0) {
+ ERROR("No partitions specified\n");
+ return -1;
+ }
+
+ offset = im.parts[0].partition_offset;
+ for (i = 0; i < im.part_count; i++)
+ {
+ part_data_t* d = &im.parts[i];
+
+ if (stat(d->filename, &d->stats) < 0) {
+ ERROR("Couldn't stat file '%s' from part '%s'\n",
+ d->filename, d->partition_name);
+ return -2;
+ }
+
+ if (d->stats.st_size == 0) {
+ ERROR("File '%s' from part '%s' is empty!\n",
+ d->filename, d->partition_name);
+ return -3;
+ }
+
+ if (d->stats.st_size > d->partition_length) {
+ ERROR("File '%s' too big (%d) - max size: 0x%08X (exceeds %lu bytes)\n",
+ d->filename, i, d->partition_length,
+ d->stats.st_size - d->partition_length);
+ return -4;
+ }
+
+ if (d->partition_offset < offset)
+ d->partition_offset = offset;
+
+ if (zero_part_baseaddr) {
+ d->partition_baseaddr = 0;
+ } else {
+ d->partition_baseaddr =
+ im.flash_baseaddr + d->partition_offset;
+ }
+ offset += d->partition_length;
+ }
+
+ return 0;
+}
+
+static int build_image(void)
+{
+ char* mem;
+ char* ptr;
+ u_int32_t mem_size;
+ FILE* f;
+ int i;
+
+ /* build in-memory buffer */
+ mem_size = sizeof(header_t) + sizeof(signature_t);
+ for (i = 0; i < im.part_count; ++i) {
+ part_data_t* d = &im.parts[i];
+ mem_size += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);
+ }
+
+ mem = (char*)calloc(mem_size, 1);
+ if (mem == NULL) {
+ ERROR("Cannot allocate memory chunk of size '%u'\n", mem_size);
+ return -1;
+ }
+
+ /* write header */
+ write_header(mem, im.version);
+ ptr = mem + sizeof(header_t);
+
+ /* write all parts */
+ for (i = 0; i < im.part_count; ++i) {
+ part_data_t* d = &im.parts[i];
+ int rc;
+ if ((rc = write_part(ptr, d)) != 0) {
+ ERROR("ERROR: failed writing part %u '%s'\n", i, d->partition_name);
+ return -1;
+ }
+ ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);
+ }
+
+
+ /* write signature */
+ write_signature(mem, mem_size - sizeof(signature_t));
+
+ /* write in-memory buffer into file */
+ if ((f = fopen(im.outputfile, "w")) == NULL) {
+ ERROR("Can not create output file: '%s'\n", im.outputfile);
+ return -10;
+ }
+
+ if (fwrite(mem, mem_size, 1, f) != 1) {
+ ERROR("Could not write %d bytes into file: '%s'\n",
+ mem_size, im.outputfile);
+ return -11;
+ }
+
+ free(mem);
+ fclose(f);
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ int o, rc;
+
+ memset(&im, 0, sizeof(im));
+
+ strcpy(im.outputfile, DEFAULT_OUTPUT_FILE);
+ strcpy(im.version, DEFAULT_VERSION);
+ memcpy(im.magic, MAGIC_HEADER, MAGIC_LENGTH);
+ im.flash_baseaddr = DEFAULT_FLASH_BASE;
+
+ while ((o = getopt(argc, argv, "f:hm:o:p:v:z")) != -1)
+ {
+ switch (o) {
+ case 'f':
+ if (optarg)
+ if (str2u32(optarg, &im.flash_baseaddr)) {
+ ERROR("Invalid flash start address %s\n", optarg);
+ return -1;
+ }
+ break;
+ case 'h':
+ usage(argv[0]);
+ return -1;
+ case 'm':
+ if (optarg) {
+ if (strlen(optarg) != MAGIC_LENGTH) {
+ ERROR("Invalid magic %s\n", optarg);
+ return -1;
+ }
+
+ memcpy(im.magic, optarg, MAGIC_LENGTH);
+ }
+ break;
+ case 'o':
+ if (optarg)
+ strncpy(im.outputfile, optarg, sizeof(im.outputfile));
+ break;
+ case 'p':
+ if (optarg) {
+ if (image_layout_add_partition(optarg))
+ return -1;
+ }
+ break;
+ case 'v':
+ if (optarg)
+ strncpy(im.version, optarg, sizeof(im.version));
+ break;
+ case 'z':
+ zero_part_baseaddr = 1;
+ break;
+ }
+ }
+
+ rc = image_layout_verify();
+ if (rc) {
+ ERROR("Failed validating firmware layout - error code: %d\n",
+ rc);
+ return -4;
+ }
+
+ print_image_info();
+
+ rc = build_image();
+ if (rc) {
+ ERROR("Failed building image file '%s' - error code: %d\n",
+ im.outputfile, rc);
+ return -5;
+ }
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/mkheader_gemtek.c b/tools/firmware-utils/src/mkheader_gemtek.c
new file mode 100644
index 0000000..9e618ef
--- /dev/null
+++ b/tools/firmware-utils/src/mkheader_gemtek.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2014 Claudio Leite <leitec@staticky.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Builds a proper flash image for routers using some Gemtek
+ * OEM boards. These include the Airlink101 AR725W, the
+ * Asante SmartHub 600 (AWRT-600N), and Linksys WRT100/110.
+ *
+ * The resulting image is compatible with the factory firmware
+ * web upgrade and TFTP interface.
+ *
+ * To build:
+ * gcc -O2 -o mkheader_gemtek mkheader_gemtek.c -lz
+ *
+ * Claudio Leite <leitec@staticky.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <zlib.h> /* for crc32() */
+
+/*
+ * The header is in little-endian format. In case
+ * we are on a BE host, we need to swap binary
+ * values.
+ */
+#ifdef __APPLE__
+# include <libkern/OSByteOrder.h>
+# define le32 OSSwapHostToLittleInt32
+#else
+# if defined(__linux__)
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define CPU_BIG_ENDIAN
+# endif
+# else
+# include <sys/endian.h> /* BSD's should have this */
+# if _BYTE_ORDER == _BIG_ENDIAN
+# define CPU_BIG_ENDIAN
+# endif
+# endif
+# ifdef CPU_BIG_ENDIAN
+# define le32(x) (((x & 0xff000000) >> 24) | \
+ ((x & 0x00ff0000) >> 8) | \
+ ((x & 0x0000ff00) << 8) | \
+ ((x & 0x000000ff) << 24))
+# else
+# define le32(x) (x)
+# endif
+#endif
+
+struct gemtek_header {
+ uint8_t magic[4];
+ uint8_t version[4];
+ uint32_t product_id;
+ uint32_t imagesz;
+ uint32_t checksum;
+ uint32_t fast_checksum;
+ uint8_t build[4];
+ uint8_t lang[4];
+};
+
+#define HDRLEN sizeof(struct gemtek_header)
+
+struct machines {
+ char *desc;
+ char *id;
+ uint32_t maxsize;
+ struct gemtek_header header;
+};
+
+struct machines mach_def[] = {
+ {"Airlink101 AR725W", "ar725w", 0x340000,
+ {"GMTK", "1003", le32(0x03000001), 0, 0,
+ 0, "01\0\0", "EN\0\0"}},
+ {"Asante AWRT-600N", "awrt600n", 0x340000,
+ {"A600", "1005", le32(0x03000001), 0, 0,
+ 0, "01\0\0", "EN\0\0"}},
+ {"Linksys WRT100", "wrt100", 0x320000,
+ {"GMTK", "1007", le32(0x03040001), 0, 0,
+ 0, "2\0\0\0", "EN\0\0"}},
+ {"Linksys WRT110", "wrt110", 0x320000,
+ {"GMTK", "1007", le32(0x03040001), 0, 0,
+ 0, "2\0\0\0", "EN\0\0"}},
+ {0}
+};
+
+int
+main(int argc, char *argv[])
+{
+ unsigned long res, flen;
+ struct gemtek_header my_hdr;
+ FILE *f, *f_out;
+ int image_type = -1, index;
+ uint8_t *buf;
+ uint32_t crc;
+
+ if (argc < 3) {
+ fprintf(stderr, "mkheader_gemtek <uImage> <webflash image> [machine ID]\n");
+ fprintf(stderr, " where [machine ID] is one of:\n");
+ for (index = 0; mach_def[index].desc != 0; index++) {
+ fprintf(stderr, " %-10s %s", mach_def[index].id, mach_def[index].desc);
+ if (index == 0)
+ fprintf(stderr, " (default)\n");
+ else
+ fprintf(stderr, "\n");
+ }
+
+ exit(-1);
+ }
+
+ if (argc == 4) {
+ for(index = 0; mach_def[index].id != 0; index++) {
+ if(strcmp(mach_def[index].id, argv[3]) == 0) {
+ image_type = index;
+ break;
+ }
+ }
+
+ if(image_type == -1) {
+ fprintf(stderr, "\nERROR: invalid machine type\n");
+ exit(-1);
+ }
+ } else
+ image_type = 0;
+
+ printf("Opening %s...\n", argv[1]);
+
+ f = fopen(argv[1], "r");
+ if(!f) {
+ fprintf(stderr, "\nERROR: couldn't open input image\n");
+ exit(-1);
+ }
+
+ fseek(f, 0, SEEK_END);
+ flen = (unsigned long) ftell(f);
+
+ printf(" %lu (0x%lX) bytes long\n", flen, flen);
+
+ if (flen > mach_def[image_type].maxsize) {
+ fprintf(stderr, "\nERROR: image exceeds maximum compatible size\n");
+ goto f_error;
+ }
+
+ buf = malloc(flen + HDRLEN);
+ if (!buf) {
+ fprintf(stderr, "\nERROR: couldn't allocate buffer\n");
+ goto f_error;
+ }
+ rewind(f);
+ res = fread(buf + HDRLEN, 1, flen, f);
+ if (res != flen) {
+ perror("Couldn't read entire file: fread()");
+ goto f_error;
+ }
+ fclose(f);
+
+ printf("\nCreating %s...\n", argv[2]);
+
+ memcpy(&my_hdr, &mach_def[image_type].header, HDRLEN);
+
+ printf(" Using %s magic\n", mach_def[image_type].desc);
+
+ my_hdr.imagesz = le32(flen + HDRLEN);
+ memcpy(my_hdr.lang, "EN", 2);
+
+ memcpy(buf, &my_hdr, HDRLEN);
+
+ crc = crc32(0, buf, flen + HDRLEN);
+ printf(" CRC32: %08X\n", crc);
+
+ my_hdr.checksum = le32(crc);
+ memcpy(buf, &my_hdr, HDRLEN);
+
+ printf(" Writing...\n");
+
+ f_out = fopen(argv[2], "w");
+ if(!f_out) {
+ fprintf(stderr, "\nERROR: couldn't open output image\n");
+ exit(-1);
+ }
+
+ fwrite(buf, 1, flen + HDRLEN, f_out);
+
+ fclose(f_out);
+
+ free(buf);
+ return 0;
+
+f_error:
+ fclose(f);
+ exit(-1);
+}
diff --git a/tools/firmware-utils/src/mkhilinkfw.c b/tools/firmware-utils/src/mkhilinkfw.c
new file mode 100644
index 0000000..99322d4
--- /dev/null
+++ b/tools/firmware-utils/src/mkhilinkfw.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2013 Jeff Kent <jeff@jkent.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This tool encrypts and decrypts uImage formatted firmware for Hilink
+ * HLK-RM04 wireless modules. It will also truncate a dump of mtd6 and make
+ * it an image suitable for flashing via the stock firmware upgrade page.
+ *
+ * Build instructions:
+ * gcc -lcrypto hlkcrypt.c -o hlkcrypt
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <openssl/des.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define DES_KEY "H@L9K*(3"
+
+#ifndef min
+#define min(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+#endif
+
+#define IH_MAGIC 0x27051956
+#define IH_NMLEN 32
+typedef struct image_header {
+ uint32_t ih_magic; /* Image Header Magic Number */
+ uint32_t ih_hcrc; /* Image Header CRC Checksum */
+ uint32_t ih_time; /* Image Creation Timestamp */
+ uint32_t ih_size; /* Image Data Size */
+ uint32_t ih_load; /* Data Load Address */
+ uint32_t ih_ep; /* Entry Point Address */
+ uint32_t ih_dcrc; /* Image Data CRC Checksum */
+ uint8_t ih_os; /* Operating System */
+ uint8_t ih_arch; /* CPU architecture */
+ uint8_t ih_type; /* Image Type */
+ uint8_t ih_comp; /* Compression Type */
+ uint8_t ih_name[IH_NMLEN]; /* Image Name */
+} image_header_t;
+
+static int temp_fd = -1;
+static DES_key_schedule schedule;
+
+static void show_usage(const char *arg0);
+static void exit_cleanup(void);
+static void copy_file(int src, int dst);
+static void do_encrypt(void *p, off_t len);
+static void do_decrypt(void *p, off_t len);
+
+
+int main(int argc, char **argv)
+{
+ int encrypt_opt = 0;
+ int decrypt_opt = 0;
+ int input_opt = 0;
+ int output_opt = 0;
+ char *input_filename = NULL;
+ char *output_filename = NULL;
+
+ int input_fd;
+ int output_fd;
+ off_t file_len;
+ char *p;
+ char buf[sizeof(image_header_t) + 3];
+ image_header_t *header;
+
+ while (1) {
+ static struct option long_options[] = {
+ {"encrypt", no_argument, 0, 'e'},
+ {"decrypt", no_argument, 0, 'd'},
+ {"input", required_argument, 0, 'i'},
+ {"output", required_argument, 0, 'o'},
+ {0, 0, 0, 0 }
+ };
+ int option_index = 0;
+ int c = getopt_long(argc, argv, "dei:o:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'd':
+ decrypt_opt++;
+ if (decrypt_opt > 1) {
+ fprintf(stderr, "%s: decrypt may only be specified once\n",
+ argv[0]);
+ show_usage(argv[0]);
+ }
+ break;
+
+ case 'e':
+ encrypt_opt++;
+ if (encrypt_opt > 1) {
+ fprintf(stderr, "%s: encrypt may only be specified once\n",
+ argv[0]);
+ show_usage(argv[0]);
+ }
+ break;
+
+ case 'i':
+ input_opt++;
+ if (input_opt > 1) {
+ fprintf(stderr, "%s: only one input file may be specified\n",
+ argv[0]);
+ show_usage(argv[0]);
+ }
+ if (strcmp("-", optarg) != 0) {
+ input_filename = optarg;
+ }
+ break;
+
+ case 'o':
+ output_opt++;
+ if (output_opt > 1) {
+ fprintf(stderr, "%s: only one output file may be specified\n",
+ argv[0]);
+ show_usage(argv[0]);
+ }
+ if (strcmp("-", optarg) != 0) {
+ output_filename = optarg;
+ }
+ break;
+
+ case '?':
+ exit(-1);
+
+ default:
+ abort();
+ }
+ }
+
+ if (decrypt_opt && encrypt_opt) {
+ fprintf(stderr, "%s: decrypt and encrypt may not be used together\n",
+ argv[0]);
+ show_usage(argv[0]);
+ }
+
+ if (!decrypt_opt && !encrypt_opt) {
+ fprintf(stderr, "%s: neither decrypt or encrypt were specified\n",
+ argv[0]);
+ show_usage(argv[0]);
+ }
+
+ temp_fd = fileno(tmpfile());
+ if (temp_fd < 0) {
+ fprintf(stderr, "Can't create temporary file\n");
+ exit(EXIT_FAILURE);
+ }
+
+ atexit(exit_cleanup);
+ DES_set_key_unchecked((const_DES_cblock *)DES_KEY, &schedule);
+
+ if (input_filename) {
+ input_fd = open(input_filename, O_RDONLY);
+ if (input_fd < 0) {
+ fprintf(stderr, "Can't open %s for reading: %s\n", input_filename,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ copy_file(input_fd, temp_fd);
+ close(input_fd);
+ }
+ else {
+ copy_file(STDIN_FILENO, temp_fd);
+ }
+
+ file_len = lseek(temp_fd, 0, SEEK_CUR);
+ if (file_len < 64) {
+ fprintf(stderr, "Not enough data\n");
+ exit(EXIT_FAILURE);
+ }
+
+ p = mmap(0, file_len, PROT_READ|PROT_WRITE, MAP_SHARED, temp_fd, 0);
+ if (p == MAP_FAILED) {
+ fprintf(stderr, "mmap failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (encrypt_opt) {
+ header = (image_header_t *)p;
+ off_t len = min(file_len,
+ ntohl(header->ih_size) + sizeof(image_header_t));
+ if (ntohl(header->ih_magic) != IH_MAGIC) {
+ fprintf(stderr, "Header magic incorrect: "
+ "expected 0x%08X, got 0x%08X\n",
+ IH_MAGIC, ntohl(header->ih_magic));
+ munmap(p, file_len);
+ exit(EXIT_FAILURE);
+ }
+ do_encrypt(p, len);
+ munmap(p, file_len);
+ if (len != file_len) {
+ if (ftruncate(temp_fd, len) < 0) {
+ fprintf(stderr, "ftruncate failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ if (decrypt_opt) {
+ off_t header_len = min(file_len, sizeof(image_header_t) + 3);
+ memcpy(buf, p, header_len);
+ do_decrypt(buf, header_len);
+ header = (image_header_t *)buf;
+ if (ntohl(header->ih_magic) != IH_MAGIC) {
+ fprintf(stderr, "Header magic incorrect: "
+ "expected 0x%08X, got 0x%08X\n",
+ IH_MAGIC, ntohl(header->ih_magic));
+ exit(EXIT_FAILURE);
+ }
+ do_decrypt(p, file_len);
+ munmap(p, file_len);
+ }
+
+ lseek(temp_fd, 0, SEEK_SET);
+ if (output_filename) {
+ output_fd = creat(output_filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (output_fd < 0) {
+ fprintf(stderr, "Can't open %s for writing: %s\n",
+ output_filename, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ copy_file(temp_fd, output_fd);
+ close(output_fd);
+ }
+ else {
+ copy_file(temp_fd, STDOUT_FILENO);
+ }
+
+ exit(EXIT_SUCCESS);
+ return 0;
+}
+
+static void show_usage(const char *arg0)
+{
+ fprintf(stderr, "usage: %s -d|-e [-i FILE] [-o FILE]\n\n", arg0);
+ fprintf(stderr, "%-15s %s\n", "-d, --decrypt", "decrypt data");
+ fprintf(stderr, "%-15s %s\n", "-e, --encrypt", "encrypt data");
+ fprintf(stderr, "%-15s %s\n", "-i, --input", "intput file (defaults to stdin)");
+ fprintf(stderr, "%-15s %s\n", "-o, --output", "output file (defaults to stdout)");
+ exit(-1);
+}
+
+static void exit_cleanup(void)
+{
+ if (temp_fd >= 0) {
+ close(temp_fd);
+ }
+}
+
+static void copy_file(int src, int dst)
+{
+ char buf[4096];
+ ssize_t size;
+
+ while ((size = read(src, buf, 4096)) > 0) {
+ write(dst, buf, size);
+ }
+}
+
+static void do_encrypt(void *p, off_t len)
+{
+ DES_cblock *pblock;
+ int num_blocks;
+
+ num_blocks = len / 8;
+ pblock = (DES_cblock *) p;
+ while (num_blocks--) {
+ DES_ecb_encrypt(pblock, pblock, &schedule, DES_ENCRYPT);
+ pblock++;
+ }
+
+ num_blocks = (len - 3) / 8;
+ pblock = (DES_cblock *) (p + 3);
+ while (num_blocks--) {
+ DES_ecb_encrypt(pblock, pblock, &schedule, DES_ENCRYPT);
+ pblock++;
+ }
+}
+
+static void do_decrypt(void *p, off_t len)
+{
+ DES_cblock *pblock;
+ int num_blocks;
+
+ num_blocks = (len - 3) / 8;
+ pblock = (DES_cblock *) (p + 3);
+ while (num_blocks--) {
+ DES_ecb_encrypt(pblock, pblock, &schedule, DES_DECRYPT);
+ pblock++;
+ }
+
+ num_blocks = len / 8;
+ pblock = (DES_cblock *) p;
+ while (num_blocks--) {
+ DES_ecb_encrypt(pblock, pblock, &schedule, DES_DECRYPT);
+ pblock++;
+ }
+}
diff --git a/tools/firmware-utils/src/mkmylofw.c b/tools/firmware-utils/src/mkmylofw.c
new file mode 100644
index 0000000..b5958eb
--- /dev/null
+++ b/tools/firmware-utils/src/mkmylofw.c
@@ -0,0 +1,1297 @@
+/*
+ * Copyright (C) 2006-2008 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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 Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <endian.h> /* for __BYTE_ORDER */
+
+#if defined(__CYGWIN__)
+# include <byteswap.h>
+#endif
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define HOST_TO_LE16(x) (x)
+# define HOST_TO_LE32(x) (x)
+#else
+# define HOST_TO_LE16(x) bswap_16(x)
+# define HOST_TO_LE32(x) bswap_32(x)
+#endif
+
+#include "myloader.h"
+
+#define MAX_FW_BLOCKS 32
+#define MAX_ARG_COUNT 32
+#define MAX_ARG_LEN 1024
+#define FILE_BUF_LEN (16*1024)
+#define PART_NAME_LEN 32
+
+struct fw_block {
+ uint32_t addr;
+ uint32_t blocklen; /* length of the block */
+ uint32_t flags;
+
+ char *name; /* name of the file */
+ uint32_t size; /* length of the file */
+ uint32_t crc; /* crc value of the file */
+};
+
+struct fw_part {
+ struct mylo_partition mylo;
+ char name[PART_NAME_LEN];
+};
+
+#define BLOCK_FLAG_HAVEHDR 0x0001
+
+struct cpx_board {
+ char *model; /* model number*/
+ char *name; /* model name*/
+ char *desc; /* description */
+ uint16_t vid; /* vendor id */
+ uint16_t did; /* device id */
+ uint16_t svid; /* sub vendor id */
+ uint16_t sdid; /* sub device id */
+ uint32_t flash_size; /* size of flash */
+ uint32_t part_offset; /* offset of the partition_table */
+ uint32_t part_size; /* size of the partition_table */
+};
+
+#define BOARD(_vid, _did, _svid, _sdid, _flash, _mod, _name, _desc, _po, _ps) { \
+ .model = _mod, .name = _name, .desc = _desc, \
+ .vid = _vid, .did = _did, .svid = _svid, .sdid = _sdid, \
+ .flash_size = (_flash << 20), \
+ .part_offset = _po, .part_size = _ps }
+
+#define CPX_BOARD(_did, _flash, _mod, _name, _desc, _po, _ps) \
+ BOARD(VENID_COMPEX, _did, VENID_COMPEX, _did, _flash, _mod, _name, _desc, _po, _ps)
+
+#define CPX_BOARD_ADM(_did, _flash, _mod, _name, _desc) \
+ CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x10000, 0x10000)
+
+#define CPX_BOARD_AR71XX(_did, _flash, _mod, _name, _desc) \
+ CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x20000, 0x8000)
+
+#define CPX_BOARD_AR23XX(_did, _flash, _mod, _name, _desc) \
+ CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x10000, 0x10000)
+
+#define ALIGN(x,y) ((x)+((y)-1)) & ~((y)-1)
+
+char *progname;
+char *ofname = NULL;
+
+uint32_t flash_size = 0;
+int fw_num_partitions = 0;
+int fw_num_blocks = 0;
+int verblevel = 0;
+
+struct mylo_fw_header fw_header;
+struct fw_part fw_parts[MYLO_MAX_PARTITIONS];
+struct fw_block fw_blocks[MAX_FW_BLOCKS];
+struct cpx_board *board;
+
+struct cpx_board boards[] = {
+ CPX_BOARD_ADM(DEVID_COMPEX_NP18A, 4,
+ "NP18A", "Compex NetPassage 18A",
+ "Dualband Wireless A+G Internet Gateway"),
+ CPX_BOARD_ADM(DEVID_COMPEX_NP26G8M, 2,
+ "NP26G8M", "Compex NetPassage 26G (8M)",
+ "Wireless-G Broadband Multimedia Gateway"),
+ CPX_BOARD_ADM(DEVID_COMPEX_NP26G16M, 4,
+ "NP26G16M", "Compex NetPassage 26G (16M)",
+ "Wireless-G Broadband Multimedia Gateway"),
+ CPX_BOARD_ADM(DEVID_COMPEX_NP27G, 4,
+ "NP27G", "Compex NetPassage 27G",
+ "Wireless-G 54Mbps eXtended Range Router"),
+ CPX_BOARD_ADM(DEVID_COMPEX_NP28G, 4,
+ "NP28G", "Compex NetPassage 28G",
+ "Wireless 108Mbps Super-G XR Multimedia Router with 4 USB Ports"),
+ CPX_BOARD_ADM(DEVID_COMPEX_NP28GHS, 4,
+ "NP28GHS", "Compex NetPassage 28G (HotSpot)",
+ "HotSpot Solution"),
+ CPX_BOARD_ADM(DEVID_COMPEX_WP18, 4,
+ "WP18", "Compex NetPassage WP18",
+ "Wireless-G 54Mbps A+G Dualband Access Point"),
+ CPX_BOARD_ADM(DEVID_COMPEX_WP54G, 4,
+ "WP54G", "Compex WP54G",
+ "Wireless-G 54Mbps XR Access Point"),
+ CPX_BOARD_ADM(DEVID_COMPEX_WP54Gv1C, 2,
+ "WP54Gv1C", "Compex WP54G rev.1C",
+ "Wireless-G 54Mbps XR Access Point"),
+ CPX_BOARD_ADM(DEVID_COMPEX_WP54AG, 4,
+ "WP54AG", "Compex WP54AG",
+ "Wireless-AG 54Mbps XR Access Point"),
+ CPX_BOARD_ADM(DEVID_COMPEX_WPP54G, 4,
+ "WPP54G", "Compex WPP54G",
+ "Outdoor Access Point"),
+ CPX_BOARD_ADM(DEVID_COMPEX_WPP54AG, 4,
+ "WPP54AG", "Compex WPP54AG",
+ "Outdoor Access Point"),
+
+ CPX_BOARD_AR71XX(DEVID_COMPEX_WP543, 2,
+ "WP543", "Compex WP543",
+ "BareBoard"),
+ CPX_BOARD_AR71XX(DEVID_COMPEX_WPE72, 8,
+ "WPE72", "Compex WPE72",
+ "BareBoard"),
+
+ CPX_BOARD_AR23XX(DEVID_COMPEX_NP25G, 4,
+ "NP25G", "Compex NetPassage 25G",
+ "Wireless 54Mbps XR Router"),
+ CPX_BOARD_AR23XX(DEVID_COMPEX_WPE53G, 4,
+ "WPE53G", "Compex NetPassage 25G",
+ "Wireless 54Mbps XR Access Point"),
+ {.model = NULL}
+};
+
+void
+errmsgv(int syserr, const char *fmt, va_list arg_ptr)
+{
+ int save = errno;
+
+ fflush(0);
+ fprintf(stderr, "[%s] Error: ", progname);
+ vfprintf(stderr, fmt, arg_ptr);
+ if (syserr != 0) {
+ fprintf(stderr, ": %s", strerror(save));
+ }
+ fprintf(stderr, "\n");
+}
+
+void
+errmsg(int syserr, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ va_start(arg_ptr, fmt);
+ errmsgv(syserr, fmt, arg_ptr);
+ va_end(arg_ptr);
+}
+
+void
+dbgmsg(int level, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ if (verblevel >= level) {
+ fflush(0);
+ va_start(arg_ptr, fmt);
+ vfprintf(stderr, fmt, arg_ptr);
+ fprintf(stderr, "\n");
+ va_end(arg_ptr);
+ }
+}
+
+
+void
+usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct cpx_board *board;
+
+ fprintf(stream, "Usage: %s [OPTION...] <file>\n", progname);
+ fprintf(stream,
+"\n"
+" <file> write output to the <file>\n"
+"\n"
+"Options:\n"
+" -B <board> create firmware for the board specified with <board>.\n"
+" This option set vendor id, device id, subvendor id,\n"
+" subdevice id, and flash size options to the right value.\n"
+" valid <board> values:\n");
+ for (board = boards; board->model != NULL; board++){
+ fprintf(stream,
+" %-12s: %s\n",
+ board->model, board->name);
+ };
+ fprintf(stream,
+" -i <vid>:<did>[:<svid>[:<sdid>]]\n"
+" create firmware for board with vendor id <vid>, device\n"
+" id <did>, subvendor id <svid> and subdevice id <sdid>.\n"
+" -r <rev> set board revision to <rev>.\n"
+" -s <size> set flash size to <size>\n"
+" -b <addr>:<len>[:[<flags>]:<file>]\n"
+" define block at <addr> with length of <len>.\n"
+" valid <flag> values:\n"
+" h : add crc header before the file data.\n"
+" -p <addr>:<len>[:<flags>[:<param>[:<name>[:<file>]]]]\n"
+" add partition at <addr>, with size of <len> to the\n"
+" partition table, set partition name to <name>, partition \n"
+" flags to <flags> and partition parameter to <param>.\n"
+" If the <file> is specified content of the file will be \n"
+" added to the firmware image.\n"
+" valid <flag> values:\n"
+" a: this is the active partition. The bootloader loads\n"
+" the firmware from this partition.\n"
+" h: the partition data have a header.\n"
+" l: the partition data uses LZMA compression.\n"
+" p: the bootloader loads data from this partition to\n"
+" the RAM before decompress it.\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+/*
+ * Code to compute the CRC-32 table. Borrowed from
+ * gzip-1.0.3/makecrc.c.
+ */
+
+static uint32_t crc_32_tab[256];
+
+void
+init_crc_table(void)
+{
+ /* Not copyrighted 1990 Mark Adler */
+
+ uint32_t c; /* crc shift register */
+ uint32_t e; /* polynomial exclusive-or pattern */
+ int i; /* counter for all possible eight bit values */
+ int k; /* byte being shifted into crc apparatus */
+
+ /* terms of polynomial defining this crc (except x^32): */
+ static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* Make exclusive-or pattern from polynomial */
+ e = 0;
+ for (i = 0; i < sizeof(p)/sizeof(int); i++)
+ e |= 1L << (31 - p[i]);
+
+ crc_32_tab[0] = 0;
+
+ for (i = 1; i < 256; i++) {
+ c = 0;
+ for (k = i | 256; k != 1; k >>= 1) {
+ c = c & 1 ? (c >> 1) ^ e : c >> 1;
+ if (k & 1)
+ c ^= e;
+ }
+ crc_32_tab[i] = c;
+ }
+}
+
+
+void
+update_crc(uint8_t *p, uint32_t len, uint32_t *crc)
+{
+ uint32_t t;
+
+ t = *crc ^ 0xFFFFFFFFUL;
+ while (len--) {
+ t = crc_32_tab[(t ^ *p++) & 0xff] ^ (t >> 8);
+ }
+ *crc = t ^ 0xFFFFFFFFUL;
+}
+
+
+uint32_t
+get_crc(uint8_t *p, uint32_t len)
+{
+ uint32_t crc;
+
+ crc = 0;
+ update_crc(p ,len , &crc);
+ return crc;
+}
+
+
+int
+str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+
+int
+str2u16(char *arg, uint16_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) {
+ return -1;
+ }
+
+ *val = t & 0xFFFF;
+ return 0;
+}
+
+
+struct cpx_board *
+find_board(char *model){
+ struct cpx_board *board;
+ struct cpx_board *tmp;
+
+ board = NULL;
+ for (tmp = boards; tmp->model != NULL; tmp++){
+ if (strcasecmp(model, tmp->model) == 0) {
+ board = tmp;
+ break;
+ }
+ };
+
+ return board;
+}
+
+
+int
+get_file_crc(struct fw_block *ff)
+{
+ FILE *f;
+ uint8_t buf[FILE_BUF_LEN];
+ uint32_t readlen = sizeof(buf);
+ int res = -1;
+ size_t len;
+
+ if ((ff->flags & BLOCK_FLAG_HAVEHDR) == 0) {
+ res = 0;
+ goto out;
+ }
+
+ errno = 0;
+ f = fopen(ff->name,"r");
+ if (errno) {
+ errmsg(1,"unable to open file %s", ff->name);
+ goto out;
+ }
+
+ ff->crc = 0;
+ len = ff->size;
+ while (len > 0) {
+ if (len < readlen)
+ readlen = len;
+
+ errno = 0;
+ fread(buf, readlen, 1, f);
+ if (errno) {
+ errmsg(1,"unable to read from file %s", ff->name);
+ goto out_close;
+ }
+
+ update_crc(buf, readlen, &ff->crc);
+ len -= readlen;
+ }
+
+ res = 0;
+
+out_close:
+ fclose(f);
+out:
+ return res;
+}
+
+
+int
+process_files(void)
+{
+ struct fw_block *b;
+ struct stat st;
+ int i;
+
+ for (i = 0; i < fw_num_blocks; i++) {
+ b = &fw_blocks[i];
+ if ((b->addr + b->blocklen) > flash_size) {
+ errmsg(0, "block at 0x%08X is too big", b->addr);
+ return -1;
+ }
+ if (b->name == NULL)
+ continue;
+
+ if (stat(b->name, &st) < 0) {
+ errmsg(0, "stat failed on %s",b->name);
+ return -1;
+ }
+ if (b->blocklen == 0) {
+ b->blocklen = flash_size - b->addr;
+ }
+ if (st.st_size > b->blocklen) {
+ errmsg(0,"file %s is too big",b->name);
+ return -1;
+ }
+
+ b->size = st.st_size;
+ }
+
+ return 0;
+}
+
+
+int
+process_partitions(void)
+{
+ struct mylo_partition *part;
+ int i;
+
+ for (i = 0; i < fw_num_partitions; i++) {
+ part = &fw_parts[i].mylo;
+
+ if (part->addr > flash_size) {
+ errmsg(0, "invalid partition at 0x%08X", part->addr);
+ return -1;
+ }
+
+ if ((part->addr + part->size) > flash_size) {
+ errmsg(0, "partition at 0x%08X is too big", part->addr);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * routines to write data to the output file
+ */
+int
+write_out_data(FILE *outfile, uint8_t *data, size_t len, uint32_t *crc)
+{
+ errno = 0;
+
+ fwrite(data, len, 1, outfile);
+ if (errno) {
+ errmsg(1,"unable to write output file");
+ return -1;
+ }
+
+ if (crc) {
+ update_crc(data, len, crc);
+ }
+
+ return 0;
+}
+
+
+int
+write_out_desc(FILE *outfile, struct mylo_fw_blockdesc *desc, uint32_t *crc)
+{
+ return write_out_data(outfile, (uint8_t *)desc,
+ sizeof(*desc), crc);
+}
+
+
+int
+write_out_padding(FILE *outfile, size_t len, uint8_t padc, uint32_t *crc)
+{
+ uint8_t buff[512];
+ size_t buflen = sizeof(buff);
+
+ memset(buff, padc, buflen);
+
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ if (write_out_data(outfile, buff, buflen, crc))
+ return -1;
+
+ len -= buflen;
+ }
+
+ return 0;
+}
+
+
+int
+write_out_file(FILE *outfile, struct fw_block *block, uint32_t *crc)
+{
+ char buff[FILE_BUF_LEN];
+ size_t buflen = sizeof(buff);
+ FILE *f;
+ size_t len;
+
+ errno = 0;
+
+ if (block->name == NULL) {
+ return 0;
+ }
+
+ if ((block->flags & BLOCK_FLAG_HAVEHDR) != 0) {
+ struct mylo_partition_header ph;
+
+ if (get_file_crc(block) != 0)
+ return -1;
+
+ ph.crc = HOST_TO_LE32(block->crc);
+ ph.len = HOST_TO_LE32(block->size);
+
+ if (write_out_data(outfile, (uint8_t *)&ph, sizeof(ph), crc) != 0)
+ return -1;
+ }
+
+ f = fopen(block->name,"r");
+ if (errno) {
+ errmsg(1,"unable to open file: %s", block->name);
+ return -1;
+ }
+
+ len = block->size;
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ /* read data from source file */
+ errno = 0;
+ fread(buff, buflen, 1, f);
+ if (errno != 0) {
+ errmsg(1,"unable to read from file: %s",block->name);
+ return -1;
+ }
+
+ if (write_out_data(outfile, buff, buflen, crc) != 0)
+ return -1;
+
+ len -= buflen;
+ }
+
+ fclose(f);
+
+ /* align next block on a 4 byte boundary */
+ len = ALIGN(len,4) - block->size;
+ if (write_out_padding(outfile, len, 0xFF, crc))
+ return -1;
+
+ dbgmsg(1,"file %s written out", block->name);
+ return 0;
+}
+
+
+int
+write_out_header(FILE *outfile, uint32_t *crc)
+{
+ struct mylo_fw_header hdr;
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ hdr.magic = HOST_TO_LE32(MYLO_MAGIC_FIRMWARE);
+ hdr.crc = HOST_TO_LE32(fw_header.crc);
+ hdr.vid = HOST_TO_LE16(fw_header.vid);
+ hdr.did = HOST_TO_LE16(fw_header.did);
+ hdr.svid = HOST_TO_LE16(fw_header.svid);
+ hdr.sdid = HOST_TO_LE16(fw_header.sdid);
+ hdr.rev = HOST_TO_LE32(fw_header.rev);
+ hdr.fwhi = HOST_TO_LE32(fw_header.fwhi);
+ hdr.fwlo = HOST_TO_LE32(fw_header.fwlo);
+ hdr.flags = HOST_TO_LE32(fw_header.flags);
+
+ if (fseek(outfile, 0, SEEK_SET) != 0) {
+ errmsg(1,"fseek failed on output file");
+ return -1;
+ }
+
+ return write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr), crc);
+}
+
+
+int
+write_out_partitions(FILE *outfile, uint32_t *crc)
+{
+ struct mylo_partition_table p;
+ char part_names[MYLO_MAX_PARTITIONS][PART_NAME_LEN];
+ int ret;
+ int i;
+
+ if (fw_num_partitions == 0)
+ return 0;
+
+ memset(&p, 0, sizeof(p));
+ memset(part_names, 0, sizeof(part_names));
+
+ p.magic = HOST_TO_LE32(MYLO_MAGIC_PARTITIONS);
+ for (i = 0; i < fw_num_partitions; i++) {
+ struct mylo_partition *mp;
+ struct fw_part *fp;
+
+ mp = &p.partitions[i];
+ fp = &fw_parts[i];
+ mp->flags = HOST_TO_LE16(fp->mylo.flags);
+ mp->type = HOST_TO_LE16(PARTITION_TYPE_USED);
+ mp->addr = HOST_TO_LE32(fp->mylo.addr);
+ mp->size = HOST_TO_LE32(fp->mylo.size);
+ mp->param = HOST_TO_LE32(fp->mylo.param);
+
+ memcpy(part_names[i], fp->name, PART_NAME_LEN);
+ }
+
+ ret = write_out_data(outfile, (uint8_t *)&p, sizeof(p), crc);
+ if (ret)
+ return ret;
+
+ ret = write_out_data(outfile, (uint8_t *)part_names, sizeof(part_names),
+ crc);
+ return ret;
+}
+
+
+int
+write_out_blocks(FILE *outfile, uint32_t *crc)
+{
+ struct mylo_fw_blockdesc desc;
+ struct fw_block *b;
+ uint32_t dlen;
+ int i;
+
+ /*
+ * if at least one partition specified, write out block descriptor
+ * for the partition table
+ */
+ if (fw_num_partitions > 0) {
+ desc.type = HOST_TO_LE32(FW_DESC_TYPE_USED);
+ desc.addr = HOST_TO_LE32(board->part_offset);
+ desc.dlen = HOST_TO_LE32(sizeof(struct mylo_partition_table) +
+ (MYLO_MAX_PARTITIONS * PART_NAME_LEN));
+ desc.blen = HOST_TO_LE32(board->part_size);
+
+ if (write_out_desc(outfile, &desc, crc) != 0)
+ return -1;
+ }
+
+ /*
+ * write out block descriptors for each files
+ */
+ for (i = 0; i < fw_num_blocks; i++) {
+ b = &fw_blocks[i];
+
+ /* detect block size */
+ dlen = b->size;
+ if ((b->flags & BLOCK_FLAG_HAVEHDR) != 0) {
+ dlen += sizeof(struct mylo_partition_header);
+ }
+
+ /* round up to 4 bytes */
+ dlen = ALIGN(dlen, 4);
+
+ /* setup the descriptor */
+ desc.type = HOST_TO_LE32(FW_DESC_TYPE_USED);
+ desc.addr = HOST_TO_LE32(b->addr);
+ desc.dlen = HOST_TO_LE32(dlen);
+ desc.blen = HOST_TO_LE32(b->blocklen);
+
+ if (write_out_desc(outfile, &desc, crc) != 0)
+ return -1;
+ }
+
+ /*
+ * write out the null block descriptor
+ */
+ memset(&desc, 0, sizeof(desc));
+ if (write_out_desc(outfile, &desc, crc) != 0)
+ return -1;
+
+ if (write_out_partitions(outfile, crc) != 0)
+ return -1;
+
+ /*
+ * write out data for each blocks
+ */
+ for (i = 0; i < fw_num_blocks; i++) {
+ b = &fw_blocks[i];
+ if (write_out_file(outfile, b, crc) != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * argument parsing
+ */
+int
+parse_arg(char *arg, char *buf, char *argv[])
+{
+ int res = 0;
+ size_t argl;
+ char *tok;
+ char **ap = &buf;
+ int i;
+
+ if ((arg == NULL)) {
+ /* invalid argument string */
+ return -1;
+ }
+
+ argl = strlen(arg);
+ if (argl == 0) {
+ /* no arguments */
+ return res;
+ }
+
+ if (argl >= MAX_ARG_LEN) {
+ /* argument is too long */
+ argl = MAX_ARG_LEN-1;
+ }
+
+ memset(argv, 0, MAX_ARG_COUNT * sizeof(void *));
+ memcpy(buf, arg, argl);
+ buf[argl] = '\0';
+
+ for (i = 0; i < MAX_ARG_COUNT; i++) {
+ tok = strsep(ap, ":");
+ if (tok == NULL) {
+ break;
+ }
+#if 0
+ else if (tok[0] == '\0') {
+ break;
+ }
+#endif
+ argv[i] = tok;
+ res++;
+ }
+
+ return res;
+}
+
+
+int
+required_arg(char c, char *arg)
+{
+ if ((optarg != NULL) && (*arg == '-')){
+ errmsg(0,"option %c requires an argument\n", c);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+is_empty_arg(char *arg)
+{
+ int ret = 1;
+ if (arg != NULL) {
+ if (*arg) ret = 0;
+ };
+ return ret;
+}
+
+
+int
+parse_opt_flags(char ch, char *arg)
+{
+ if (required_arg(ch, arg)) {
+ goto err_out;
+ }
+
+ if (str2u32(arg, &fw_header.flags) != 0) {
+ errmsg(0,"invalid firmware flags: %s", arg);
+ goto err_out;
+ }
+
+ dbgmsg(1, "firmware flags set to %X bytes", fw_header.flags);
+
+ return 0;
+
+err_out:
+ return -1;
+}
+
+
+int
+parse_opt_size(char ch, char *arg)
+{
+ if (required_arg(ch, arg)) {
+ goto err_out;
+ }
+
+ if (str2u32(arg, &flash_size) != 0) {
+ errmsg(0,"invalid flash size: %s", arg);
+ goto err_out;
+ }
+
+ dbgmsg(1, "flash size set to %d bytes", flash_size);
+
+ return 0;
+
+err_out:
+ return -1;
+}
+
+
+int
+parse_opt_id(char ch, char *arg)
+{
+ char buf[MAX_ARG_LEN];
+ char *argv[MAX_ARG_COUNT];
+ int argc;
+ char *p;
+
+ if (required_arg(ch, arg)) {
+ goto err_out;
+ }
+
+ argc = parse_arg(arg, buf, argv);
+
+ /* processing vendor ID*/
+ p = argv[0];
+ if (is_empty_arg(p)) {
+ errmsg(0,"vendor id is missing from -%c %s",ch, arg);
+ goto err_out;
+ } else if (str2u16(p, &fw_header.vid) != 0) {
+ errmsg(0,"invalid vendor id: %s", p);
+ goto err_out;
+ }
+
+ dbgmsg(1, "vendor id is set to 0x%04X", fw_header.vid);
+
+ /* processing device ID*/
+ p = argv[1];
+ if (is_empty_arg(p)) {
+ errmsg(0,"device id is missing from -%c %s",ch, arg);
+ goto err_out;
+ } else if (str2u16(p, &fw_header.did) != 0) {
+ errmsg(0,"invalid device id: %s", p);
+ goto err_out;
+ }
+
+ dbgmsg(1, "device id is set to 0x%04X", fw_header.did);
+
+ /* processing sub vendor ID*/
+ p = argv[2];
+ if (is_empty_arg(p)) {
+ fw_header.svid = fw_header.vid;
+ } else if (str2u16(p, &fw_header.svid) != 0) {
+ errmsg(0,"invalid sub vendor id: %s", p);
+ goto err_out;
+ }
+
+ dbgmsg(1, "sub vendor id is set to 0x%04X", fw_header.svid);
+
+ /* processing device ID*/
+ p = argv[3];
+ if (is_empty_arg(p)) {
+ fw_header.sdid = fw_header.did;
+ } else if (str2u16(p, &fw_header.sdid) != 0) {
+ errmsg(0,"invalid sub device id: %s", p);
+ goto err_out;
+ }
+
+ dbgmsg(1, "sub device id is set to 0x%04X", fw_header.sdid);
+
+ /* processing revision */
+ p = argv[4];
+ if (is_empty_arg(p)) {
+ fw_header.rev = 0;
+ } else if (str2u32(arg, &fw_header.rev) != 0) {
+ errmsg(0,"invalid revision number: %s", p);
+ goto err_out;
+ }
+
+ dbgmsg(1, "board revision is set to 0x%08X", fw_header.rev);
+
+ return 0;
+
+err_out:
+ return -1;
+}
+
+
+int
+parse_opt_block(char ch, char *arg)
+{
+ char buf[MAX_ARG_LEN];
+ char *argv[MAX_ARG_COUNT];
+ int argc;
+ struct fw_block *b;
+ char *p;
+
+ if (required_arg(ch, arg)) {
+ goto err_out;
+ }
+
+ if (fw_num_blocks >= MAX_FW_BLOCKS) {
+ errmsg(0,"too many blocks specified");
+ goto err_out;
+ }
+
+ argc = parse_arg(arg, buf, argv);
+ dbgmsg(1,"processing block option %s, count %d", arg, argc);
+
+ b = &fw_blocks[fw_num_blocks++];
+
+ /* processing block address */
+ p = argv[0];
+ if (is_empty_arg(p)) {
+ errmsg(0,"no block address specified in %s", arg);
+ goto err_out;
+ } else if (str2u32(p, &b->addr) != 0) {
+ errmsg(0,"invalid block address: %s", p);
+ goto err_out;
+ }
+
+ /* processing block length */
+ p = argv[1];
+ if (is_empty_arg(p)) {
+ errmsg(0,"no block length specified in %s", arg);
+ goto err_out;
+ } else if (str2u32(p, &b->blocklen) != 0) {
+ errmsg(0,"invalid block length: %s", p);
+ goto err_out;
+ }
+
+ if (argc < 3) {
+ dbgmsg(1,"empty block %s", arg);
+ goto success;
+ }
+
+ /* processing flags */
+ p = argv[2];
+ if (is_empty_arg(p) == 0) {
+ for ( ; *p != '\0'; p++) {
+ switch (*p) {
+ case 'h':
+ b->flags |= BLOCK_FLAG_HAVEHDR;
+ break;
+ default:
+ errmsg(0, "invalid block flag \"%c\"", *p);
+ goto err_out;
+ }
+ }
+ }
+
+ /* processing file name */
+ p = argv[3];
+ if (is_empty_arg(p)) {
+ errmsg(0,"file name missing in %s", arg);
+ goto err_out;
+ }
+
+ b->name = strdup(p);
+ if (b->name == NULL) {
+ errmsg(0,"not enough memory");
+ goto err_out;
+ }
+
+success:
+
+ return 0;
+
+err_out:
+ return -1;
+}
+
+
+int
+parse_opt_partition(char ch, char *arg)
+{
+ char buf[MAX_ARG_LEN];
+ char *argv[MAX_ARG_COUNT];
+ int argc;
+ char *p;
+ struct mylo_partition *part;
+ struct fw_part *fp;
+
+ if (required_arg(ch, arg)) {
+ goto err_out;
+ }
+
+ if (fw_num_partitions >= MYLO_MAX_PARTITIONS) {
+ errmsg(0, "too many partitions specified");
+ goto err_out;
+ }
+
+ fp = &fw_parts[fw_num_partitions++];
+ part = &fp->mylo;
+
+ argc = parse_arg(arg, buf, argv);
+
+ /* processing partition address */
+ p = argv[0];
+ if (is_empty_arg(p)) {
+ errmsg(0,"partition address missing in -%c %s",ch, arg);
+ goto err_out;
+ } else if (str2u32(p, &part->addr) != 0) {
+ errmsg(0,"invalid partition address: %s", p);
+ goto err_out;
+ }
+
+ /* processing partition size */
+ p = argv[1];
+ if (is_empty_arg(p)) {
+ errmsg(0,"partition size missing in -%c %s",ch, arg);
+ goto err_out;
+ } else if (str2u32(p, &part->size) != 0) {
+ errmsg(0,"invalid partition size: %s", p);
+ goto err_out;
+ }
+
+ /* processing partition flags */
+ p = argv[2];
+ if (is_empty_arg(p) == 0) {
+ for ( ; *p != '\0'; p++) {
+ switch (*p) {
+ case 'a':
+ part->flags |= PARTITION_FLAG_ACTIVE;
+ break;
+ case 'p':
+ part->flags |= PARTITION_FLAG_PRELOAD;
+ break;
+ case 'l':
+ part->flags |= PARTITION_FLAG_LZMA;
+ break;
+ case 'h':
+ part->flags |= PARTITION_FLAG_HAVEHDR;
+ break;
+ default:
+ errmsg(0, "invalid partition flag \"%c\"", *p);
+ goto err_out;
+ }
+ }
+ }
+
+ /* processing partition parameter */
+ p = argv[3];
+ if (is_empty_arg(p)) {
+ /* set default partition parameter */
+ part->param = 0;
+ } else if (str2u32(p, &part->param) != 0) {
+ errmsg(0,"invalid partition parameter: %s", p);
+ goto err_out;
+ }
+
+ p = argv[4];
+ if (is_empty_arg(p)) {
+ /* set default partition parameter */
+ fp->name[0] = '\0';
+ } else {
+ strncpy(fp->name, p, PART_NAME_LEN);
+ }
+
+#if 1
+ if (part->size == 0) {
+ part->size = flash_size - part->addr;
+ }
+
+ /* processing file parameter */
+ p = argv[5];
+ if (is_empty_arg(p) == 0) {
+ struct fw_block *b;
+
+ if (fw_num_blocks == MAX_FW_BLOCKS) {
+ errmsg(0,"too many blocks specified", p);
+ goto err_out;
+ }
+ b = &fw_blocks[fw_num_blocks++];
+ b->name = strdup(p);
+ b->addr = part->addr;
+ b->blocklen = part->size;
+ if (part->flags & PARTITION_FLAG_HAVEHDR) {
+ b->flags |= BLOCK_FLAG_HAVEHDR;
+ }
+ }
+#endif
+
+ return 0;
+
+err_out:
+ return -1;
+}
+
+
+int
+parse_opt_board(char ch, char *arg)
+{
+ if (required_arg(ch, arg)) {
+ goto err_out;
+ }
+
+ board = find_board(arg);
+ if (board == NULL){
+ errmsg(0,"invalid/unknown board specified: %s", arg);
+ goto err_out;
+ }
+
+ fw_header.vid = board->vid;
+ fw_header.did = board->did;
+ fw_header.svid = board->svid;
+ fw_header.sdid = board->sdid;
+
+ flash_size = board->flash_size;
+
+ return 0;
+
+err_out:
+ return -1;
+}
+
+
+int
+parse_opt_rev(char ch, char *arg)
+{
+ if (required_arg(ch, arg)) {
+ return -1;
+ }
+
+ if (str2u32(arg, &fw_header.rev) != 0) {
+ errmsg(0,"invalid revision number: %s", arg);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * main
+ */
+int
+main(int argc, char *argv[])
+{
+ int optinvalid = 0; /* flag for invalid option */
+ int c;
+ int res = EXIT_FAILURE;
+
+ FILE *outfile;
+ uint32_t crc;
+
+ progname=basename(argv[0]);
+
+ memset(&fw_header, 0, sizeof(fw_header));
+
+ /* init header defaults */
+ fw_header.vid = VENID_COMPEX;
+ fw_header.did = DEVID_COMPEX_WP54G;
+ fw_header.svid = VENID_COMPEX;
+ fw_header.sdid = DEVID_COMPEX_WP54G;
+ fw_header.fwhi = 0x20000;
+ fw_header.fwlo = 0x20000;
+ fw_header.flags = 0;
+
+ opterr = 0; /* could not print standard getopt error messages */
+ while ((c = getopt(argc, argv, "b:B:f:hi:p:r:s:v")) != -1) {
+ optinvalid = 0;
+ switch (c) {
+ case 'b':
+ optinvalid = parse_opt_block(c,optarg);
+ break;
+ case 'B':
+ optinvalid = parse_opt_board(c,optarg);
+ break;
+ case 'f':
+ optinvalid = parse_opt_flags(c,optarg);
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ case 'i':
+ optinvalid = parse_opt_id(c,optarg);
+ break;
+ case 'p':
+ optinvalid = parse_opt_partition(c,optarg);
+ break;
+ case 'r':
+ optinvalid = parse_opt_rev(c,optarg);
+ break;
+ case 's':
+ optinvalid = parse_opt_size(c,optarg);
+ break;
+ case 'v':
+ verblevel++;
+ break;
+ default:
+ optinvalid = 1;
+ break;
+ }
+ if (optinvalid != 0 ){
+ errmsg(0, "invalid option: -%c", optopt);
+ goto out;
+ }
+ }
+
+ if (optind == argc) {
+ errmsg(0, "no output file specified");
+ goto out;
+ }
+
+ ofname = argv[optind++];
+
+ if (optind < argc) {
+ errmsg(0, "invalid option: %s", argv[optind]);
+ goto out;
+ }
+
+ if (!board) {
+ errmsg(0, "no board specified");
+ goto out;
+ }
+
+ if (flash_size == 0) {
+ errmsg(0, "no flash size specified");
+ goto out;
+ }
+
+ if (process_files() != 0) {
+ goto out;
+ }
+
+ if (process_partitions() != 0) {
+ goto out;
+ }
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ errmsg(1, "could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ crc = 0;
+ init_crc_table();
+
+ if (write_out_header(outfile, &crc) != 0)
+ goto out_flush;
+
+ if (write_out_blocks(outfile, &crc) != 0)
+ goto out_flush;
+
+ fw_header.crc = crc;
+ if (write_out_header(outfile, NULL) != 0)
+ goto out_flush;
+
+ dbgmsg(1,"Firmware file %s completed.", ofname);
+
+ res = EXIT_SUCCESS;
+
+out_flush:
+ fflush(outfile);
+ fclose(outfile);
+ if (res != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+out:
+ return res;
+}
diff --git a/tools/firmware-utils/src/mkplanexfw.c b/tools/firmware-utils/src/mkplanexfw.c
new file mode 100644
index 0000000..0b71f80
--- /dev/null
+++ b/tools/firmware-utils/src/mkplanexfw.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "sha1.h"
+
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+# define HOST_TO_BE32(x) (x)
+# define BE32_TO_HOST(x) (x)
+#else
+# define HOST_TO_BE32(x) bswap_32(x)
+# define BE32_TO_HOST(x) bswap_32(x)
+#endif
+
+
+struct planex_hdr {
+ uint8_t sha1sum[20];
+ char version[8];
+ uint8_t unk1[2];
+ uint32_t datalen;
+} __attribute__ ((packed));
+
+struct board_info {
+ char *id;
+ uint32_t seed;
+ uint8_t unk[2];
+ uint32_t datalen;
+};
+
+/*
+ * Globals
+ */
+static char *ifname;
+static char *progname;
+static char *ofname;
+static char *version = "1.00.00";
+
+static char *board_id;
+static struct board_info *board;
+
+static struct board_info boards[] = {
+ {
+ .id = "MZK-W04NU",
+ .seed = 2,
+ .unk = {0x04, 0x08},
+ .datalen = 0x770000,
+ }, {
+ .id = "MZK-W300NH",
+ .seed = 4,
+ .unk = {0x00, 0x00},
+ .datalen = 0x770000,
+ }, {
+ /* terminating entry */
+ }
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+static struct board_info *find_board(char *id)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->id != NULL; board++){
+ if (strcasecmp(id, board->id) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>\n"
+" -i <file> read input from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -v <version> set image version to <version>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+ int res = EXIT_FAILURE;
+ int buflen;
+ int err;
+ struct stat st;
+ char *buf;
+ struct planex_hdr *hdr;
+ sha1_context ctx;
+ uint32_t seed;
+
+ FILE *outfile, *infile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "B:i:o:v:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'B':
+ board_id = optarg;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'v':
+ version = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (board_id == NULL) {
+ ERR("no board specified");
+ goto err;
+ }
+
+ board = find_board(board_id);
+ if (board == NULL) {
+ ERR("unknown board '%s'", board_id);
+ goto err;
+ };
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto err;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto err;
+ }
+
+ err = stat(ifname, &st);
+ if (err){
+ ERRS("stat failed on %s", ifname);
+ goto err;
+ }
+
+ if (st.st_size > board->datalen) {
+ ERR("file '%s' is too big - max size: 0x%08X (exceeds %lu bytes)\n",
+ ifname, board->datalen, st.st_size - board->datalen);
+ goto err;
+ }
+
+ buflen = board->datalen + 0x10000;
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto err;
+ }
+
+ memset(buf, 0xff, buflen);
+ hdr = (struct planex_hdr *)buf;
+
+ hdr->datalen = HOST_TO_BE32(board->datalen);
+ hdr->unk1[0] = board->unk[0];
+ hdr->unk1[1] = board->unk[1];
+
+ snprintf(hdr->version, sizeof(hdr->version), "%s", version);
+
+ infile = fopen(ifname, "r");
+ if (infile == NULL) {
+ ERRS("could not open \"%s\" for reading", ifname);
+ goto err_free;
+ }
+
+ errno = 0;
+ fread(buf + sizeof(*hdr), st.st_size, 1, infile);
+ if (errno != 0) {
+ ERRS("unable to read from file %s", ifname);
+ goto err_close_in;
+ }
+
+ seed = HOST_TO_BE32(board->seed);
+ sha1_starts(&ctx);
+ sha1_update(&ctx, (uchar *) &seed, sizeof(seed));
+ sha1_update(&ctx, buf + sizeof(*hdr), board->datalen);
+ sha1_finish(&ctx, hdr->sha1sum);
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto err_close_in;
+ }
+
+ errno = 0;
+ fwrite(buf, buflen, 1, outfile);
+ if (errno) {
+ ERRS("unable to write to file %s", ofname);
+ goto err_close_out;
+ }
+
+ res = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(outfile);
+
+ err_close_out:
+ fclose(outfile);
+ if (res != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+
+ err_close_in:
+ fclose(infile);
+
+ err_free:
+ free(buf);
+
+ err:
+ return res;
+}
+
diff --git a/tools/firmware-utils/src/mkporayfw.c b/tools/firmware-utils/src/mkporayfw.c
new file mode 100644
index 0000000..6ec4f32
--- /dev/null
+++ b/tools/firmware-utils/src/mkporayfw.c
@@ -0,0 +1,791 @@
+/*
+ * Builder/viewer/extractor utility for Poray firmware image files
+ *
+ * Copyright (C) 2013 Michel Stempin <michel.stempin@wanadoo.fr>
+ * Copyright (C) 2013 Felix Kaechele <felix@fetzig.org>
+ * Copyright (C) 2013 <admin@openschemes.com>
+ *
+ * This tool is based on:
+ * TP-Link firmware upgrade tool.
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Itself based on:
+ * TP-Link WR941 V2 firmware checksum fixing tool.
+ * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+# define HOST_TO_BE32(x) (x)
+# define BE32_TO_HOST(x) (x)
+# define HOST_TO_LE32(x) bswap_32(x)
+# define LE32_TO_HOST(x) bswap_32(x)
+#else
+# define HOST_TO_BE32(x) bswap_32(x)
+# define BE32_TO_HOST(x) bswap_32(x)
+# define HOST_TO_LE32(x) (x)
+# define LE32_TO_HOST(x) (x)
+#endif
+
+/* Fixed header flags */
+#define HEADER_FLAGS 0x020e0000
+
+/* Recognized Hardware ID magic */
+#define HWID_HAME_MPR_A1_L8 0x32473352
+#define HWID_PORAY_R50B 0x31353033
+#define HWID_PORAY_R50D 0x33353033
+#define HWID_PORAY_R50E 0x34353033
+#define HWID_PORAY_M3 0x31353335
+#define HWID_PORAY_M4 0x32353335
+#define HWID_PORAY_Q3 0x33353335
+#define HWID_PORAY_X5_X6 0x35353335
+#define HWID_PORAY_X8 0x36353335
+#define HWID_PORAY_X1 0x38353335
+#define HWID_NEXX_WT1520 0x30353332
+#define HWID_NEXX_WT3020 0x30323033
+#define HWID_A5_V11 0x32473352
+
+/* Recognized XOR obfuscation keys */
+#define KEY_HAME 0
+#define KEY_PORAY_1 1
+#define KEY_PORAY_2 2
+#define KEY_PORAY_3 3
+#define KEY_PORAY_4 4
+#define KEY_NEXX_1 5
+#define KEY_NEXX_2 6
+#define KEY_A5_V11 7
+
+/* XOR key length */
+#define KEY_LEN 15
+
+struct file_info {
+ char *file_name; /* Name of the file */
+ uint32_t file_size; /* Length of the file */
+};
+
+struct fw_header {
+ uint32_t hw_id; /* Hardware id */
+ uint32_t firmware_len; /* Firmware data length */
+ uint32_t flags; /* Header flags */
+ uint8_t pad[16];
+} __attribute__ ((packed));
+
+struct flash_layout {
+ char *id;
+ uint32_t fw_max_len;
+};
+
+struct board_info {
+ char *id;
+ uint32_t hw_id;
+ char *layout_id;
+ uint32_t key;
+};
+
+/*
+ * Globals
+ */
+static char *ofname;
+static char *progname;
+
+static char *board_id;
+static struct board_info *board;
+static char *layout_id;
+static struct flash_layout *layout;
+static char *opt_hw_id;
+static uint32_t hw_id;
+static struct file_info firmware_info;
+static uint32_t firmware_len = 0;
+
+static int inspect = 0;
+static int extract = 0;
+
+static uint8_t key[][KEY_LEN] = {
+ {0xC8, 0x3C, 0x3A, 0x93, 0xA2, 0x95, 0xC3, 0x63, 0x48, 0x45, 0x58, 0x09, 0x12, 0x03, 0x08},
+ {0x89, 0x6B, 0x5A, 0x93, 0x92, 0x95, 0xC3, 0x63, 0xD0, 0xA3, 0x9C, 0x92, 0x2E, 0xE6, 0xC7},
+ {0xC9, 0x1C, 0x3A, 0x93, 0x92, 0x95, 0xC3, 0x63, 0xD0, 0xA3, 0x9C, 0x92, 0x2E, 0xE6, 0xC7},
+ {0x19, 0x1B, 0x3A, 0x93, 0x92, 0x95, 0xC3, 0x63, 0xD0, 0xA3, 0x9C, 0x92, 0x2E, 0xE6, 0xC7},
+ {0x79, 0x7B, 0x7A, 0x93, 0x92, 0x95, 0xC3, 0x63, 0xD0, 0xA3, 0x9C, 0x92, 0x2E, 0xE6, 0xC7},
+ {0x19, 0x1C, 0x4A, 0x93, 0x96, 0x95, 0xC3, 0x63, 0xD0, 0xA3, 0x9C, 0x92, 0x2E, 0x16, 0xC6},
+ {0x39, 0x1C, 0x4A, 0x93, 0x96, 0x95, 0xC3, 0x63, 0xD0, 0xA3, 0x9C, 0x92, 0x2E, 0x16, 0xC6},
+ {0xC8, 0x3C, 0x3A, 0x93, 0xA2, 0x95, 0xC3, 0x63, 0x48, 0x45, 0x58, 0x09, 0x20, 0x11, 0x08},
+};
+
+static struct flash_layout layouts[] = {
+ {
+ .id = "4M",
+ .fw_max_len = 0x3c0000,
+ }, {
+ .id = "8M",
+ .fw_max_len = 0x7c0000,
+ }, {
+ /* terminating entry */
+ }
+};
+
+static struct board_info boards[] = {
+ {
+ .id = "A5-V11",
+ .hw_id = HWID_A5_V11,
+ .layout_id = "4M",
+ .key = KEY_A5_V11,
+ }, {
+ .id = "MPR-A1",
+ .hw_id = HWID_HAME_MPR_A1_L8,
+ .layout_id = "4M",
+ .key = KEY_HAME,
+ }, {
+ .id = "MPR-L8",
+ .hw_id = HWID_HAME_MPR_A1_L8,
+ .layout_id = "4M",
+ .key = KEY_HAME,
+ }, {
+ .id = "R50B",
+ .hw_id = HWID_PORAY_R50B,
+ .layout_id = "4M",
+ .key = KEY_PORAY_2,
+ }, {
+ .id = "R50D",
+ .hw_id = HWID_PORAY_R50D,
+ .layout_id = "4M",
+ .key = KEY_PORAY_3,
+ }, {
+ .id = "R50E",
+ .hw_id = HWID_PORAY_R50E,
+ .layout_id = "4M",
+ .key = KEY_PORAY_4,
+ }, {
+ .id = "M3",
+ .hw_id = HWID_PORAY_M3,
+ .layout_id = "4M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "M4",
+ .hw_id = HWID_PORAY_M4,
+ .layout_id = "4M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "Q3",
+ .hw_id = HWID_PORAY_Q3,
+ .layout_id = "4M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "X5 or X6",
+ .hw_id = HWID_PORAY_X5_X6,
+ .layout_id = "8M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "X5",
+ .hw_id = HWID_PORAY_X5_X6,
+ .layout_id = "8M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "X6",
+ .hw_id = HWID_PORAY_X5_X6,
+ .layout_id = "8M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "X8",
+ .hw_id = HWID_PORAY_X8,
+ .layout_id = "8M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "X1",
+ .hw_id = HWID_PORAY_X1,
+ .layout_id = "8M",
+ .key = KEY_PORAY_1,
+ }, {
+ .id = "WT1520",
+ .hw_id = HWID_NEXX_WT1520,
+ .layout_id = "4M",
+ .key = KEY_NEXX_1,
+ }, {
+ .id = "WT1520",
+ .hw_id = HWID_NEXX_WT1520,
+ .layout_id = "8M",
+ .key = KEY_NEXX_1,
+ }, {
+ .id = "WT3020",
+ .hw_id = HWID_NEXX_WT3020,
+ .layout_id = "4M",
+ .key = KEY_NEXX_2,
+ }, {
+ .id = "WT3020",
+ .hw_id = HWID_NEXX_WT3020,
+ .layout_id = "8M",
+ .key = KEY_NEXX_2,
+ }, {
+
+
+
+
+ /* terminating entry */
+ }
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ":%s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+/*
+ * Find a board by its name
+ */
+static struct board_info *find_board(char *id)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->id != NULL; board++){
+ if (strcasecmp(id, board->id) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+/*
+ * Find a board by its hardware ID
+ */
+static struct board_info *find_board_by_hwid(uint32_t hw_id)
+{
+ struct board_info *board;
+
+ for (board = boards; board->id != NULL; board++) {
+ if (hw_id == board->hw_id)
+ return board;
+ };
+
+ return NULL;
+}
+
+/*
+ * Find a Flash memory layout by its name
+ */
+static struct flash_layout *find_layout(char *id)
+{
+ struct flash_layout *ret;
+ struct flash_layout *l;
+
+ ret = NULL;
+ for (l = layouts; l->id != NULL; l++){
+ if (strcasecmp(id, l->id) == 0) {
+ ret = l;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+/*
+ * Display usage
+ */
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>\n"
+" -H <hwid> use hardware id specified with <hwid>\n"
+" -F <id> use flash layout specified with <id>\n"
+" -f <file> read firmware image from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -i inspect given firmware file (requires -f)\n"
+" -x extract combined kernel and rootfs while inspecting (implies -i)\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+/*
+ * Get file statistics
+ */
+static int get_file_stat(struct file_info *fdata)
+{
+ struct stat st;
+ int res;
+
+ if (fdata->file_name == NULL) {
+ return 0;
+ }
+ res = stat(fdata->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", fdata->file_name);
+ return res;
+ }
+
+ fdata->file_size = st.st_size;
+ return 0;
+}
+
+/*
+ * Read file into buffer
+ */
+static int read_to_buf(struct file_info *fdata, uint8_t *buf)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(fdata->file_name, "rb");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", fdata->file_name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, fdata->file_size, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", fdata->file_name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+ out_close:
+ fclose(f);
+ out:
+ return ret;
+}
+
+/*
+ * Check command line options
+ */
+static int check_options(void)
+{
+ int ret;
+
+ if (firmware_info.file_name == NULL) {
+ ERR("no firmware image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&firmware_info);
+ if (ret)
+ return ret;
+
+ if (inspect)
+ return 0;
+
+ if (board_id == NULL && opt_hw_id == NULL) {
+ ERR("either board or hardware id must be specified");
+ return -1;
+ }
+
+ if (board_id) {
+ board = find_board(board_id);
+ if (board == NULL) {
+ ERR("unknown/unsupported board id \"%s\"", board_id);
+ return -1;
+ }
+ if (layout_id == NULL) {
+ layout_id = board->layout_id;
+ }
+ hw_id = board->hw_id;
+ } else {
+ hw_id = strtoul(opt_hw_id, NULL, 0);
+ board = find_board_by_hwid(hw_id);
+ if (layout_id == NULL) {
+ layout_id = board->layout_id;
+ }
+ }
+
+ layout = find_layout(layout_id);
+ if (layout == NULL) {
+ ERR("unknown flash layout \"%s\"", layout_id);
+ return -1;
+ }
+
+ firmware_len = firmware_info.file_size;
+
+ if (firmware_info.file_size >
+ layout->fw_max_len - sizeof (struct fw_header)) {
+ ERR("firmware image is too big");
+ return -1;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Fill in firmware header
+ */
+static void fill_header(uint8_t *buf)
+{
+ struct fw_header *hdr = (struct fw_header *) buf;
+
+ memset(hdr, 0, sizeof (struct fw_header));
+ hdr->hw_id = HOST_TO_LE32(hw_id);
+ hdr->firmware_len = HOST_TO_LE32(firmware_len);
+ hdr->flags = HOST_TO_LE32(HEADER_FLAGS);
+}
+
+/*
+ * Compute firmware checksum
+ */
+static uint16_t checksum_fw(uint8_t *data, int len)
+{
+ int i;
+ int32_t checksum = 0;
+
+ for (i = 0; i < len - 1; i += 2) {
+ checksum += (data[i + 1] << 8) | data[i];
+ }
+ if (i < len) {
+ checksum += data[i];
+ }
+ checksum = checksum + (checksum >> 16) + 0xffff;
+ checksum = ~(checksum + (checksum >> 16)) & 0xffff;
+ return (uint16_t) checksum;
+}
+
+/*
+ * (De)obfuscate firmware using an XOR operation with a fixed length key
+ */
+static void xor_fw(uint8_t *data, int len)
+{
+ int i;
+
+ for (i = 0; i <= len; i++) {
+ data[i] ^= key[board->key][i % KEY_LEN];
+ }
+}
+
+/*
+ * Write firmware to file
+ */
+static int write_fw(uint8_t *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "wb");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ DBG("firmware file \"%s\" completed", ofname);
+
+ ret = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+ out:
+ return ret;
+}
+
+/*
+ * Build firmware file
+ */
+static int build_fw(void)
+{
+ int buflen;
+ uint8_t *buf, *p;
+ int ret = EXIT_FAILURE;
+ int writelen = 0;
+ uint16_t checksum;
+
+ buflen = layout->fw_max_len;
+
+ buf = (uint8_t *) malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ memset(buf, 0xff, buflen);
+ p = buf + sizeof (struct fw_header);
+ ret = read_to_buf(&firmware_info, p);
+ if (ret) {
+ goto out_free_buf;
+ }
+ writelen = sizeof (struct fw_header) + firmware_len + 2;
+
+ /* Fill in header */
+ fill_header(buf);
+
+ /* Compute firmware checksum */
+ checksum = checksum_fw(buf + sizeof (struct fw_header), firmware_len);
+
+ /* Cannot use network order function because checksum is not word-aligned */
+ buf[writelen - 1] = checksum >> 8;
+ buf[writelen - 2] = checksum & 0xff;
+
+ /* XOR obfuscate firmware */
+ xor_fw(buf + sizeof (struct fw_header), firmware_len + 2);
+
+ /* Write firmware file */
+ ret = write_fw(buf, writelen);
+ if (ret) {
+ goto out_free_buf;
+ }
+ ret = EXIT_SUCCESS;
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+/* Helper functions to inspect_fw() representing different output formats */
+static inline void inspect_fw_pstr(char *label, char *str)
+{
+ printf("%-23s: %s\n", label, str);
+}
+
+static inline void inspect_fw_phex(char *label, uint32_t val)
+{
+ printf("%-23s: 0x%08x\n", label, val);
+}
+
+static inline void inspect_fw_phexpost(char *label,
+ uint32_t val, char *post)
+{
+ printf("%-23s: 0x%08x (%s)\n", label, val, post);
+}
+
+static inline void inspect_fw_phexdef(char *label,
+ uint32_t val, uint32_t defval)
+{
+ printf("%-23s: 0x%08x ", label, val);
+
+ if (val == defval) {
+ printf("(== OpenWrt default)\n");
+ } else {
+ printf("(OpenWrt default: 0x%08x)\n", defval);
+ }
+}
+
+static inline void inspect_fw_phexexp(char *label,
+ uint32_t val, uint32_t expval)
+{
+ printf("%-23s: 0x%08x ", label, val);
+
+ if (val == expval) {
+ printf("(ok)\n");
+ } else {
+ printf("(expected: 0x%08x)\n", expval);
+ }
+}
+
+static inline void inspect_fw_phexdec(char *label, uint32_t val)
+{
+ printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
+}
+
+static inline void inspect_fw_pchecksum(char *label,
+ uint16_t val, uint16_t expval)
+{
+ printf("%-23s: 0x%04x ", label, val);
+ if (val == expval) {
+ printf("(ok)\n");
+ } else {
+ printf("(expected: 0x%04x)\n", expval);
+ }
+}
+
+static int inspect_fw(void)
+{
+ uint8_t *buf;
+ struct fw_header *hdr;
+ int ret = EXIT_FAILURE;
+ uint16_t computed_checksum, file_checksum;
+
+ buf = (uint8_t *) malloc(firmware_info.file_size);
+ if (!buf) {
+ ERR("no memory for buffer!\n");
+ goto out;
+ }
+
+ ret = read_to_buf(&firmware_info, buf);
+ if (ret) {
+ goto out_free_buf;
+ }
+ hdr = (struct fw_header *)buf;
+
+ inspect_fw_pstr("File name", firmware_info.file_name);
+ inspect_fw_phexdec("File size", firmware_info.file_size);
+
+ printf("\n");
+
+ inspect_fw_phexdec("Header size", sizeof (struct fw_header));
+ board = find_board_by_hwid(LE32_TO_HOST(hdr->hw_id));
+ if (board) {
+ layout = find_layout(board->layout_id);
+ inspect_fw_phexpost("Hardware ID",
+ LE32_TO_HOST( hdr->hw_id), board->id);
+ } else {
+ inspect_fw_phexpost("Hardware ID",
+ LE32_TO_HOST(hdr->hw_id), "unknown");
+ }
+ inspect_fw_phexdec("Firmware data length",
+ LE32_TO_HOST(hdr->firmware_len));
+
+ inspect_fw_phexexp("Flags",
+ LE32_TO_HOST(hdr->flags), HEADER_FLAGS);
+ printf("\n");
+
+ /* XOR unobfuscate firmware */
+ xor_fw(buf + sizeof (struct fw_header), LE32_TO_HOST(hdr->firmware_len) + 2);
+
+ /* Compute firmware checksum */
+ computed_checksum = checksum_fw(buf + sizeof (struct fw_header), LE32_TO_HOST(hdr->firmware_len));
+
+ /* Cannot use network order function because checksum is not word-aligned */
+ file_checksum = (buf[firmware_info.file_size - 1] << 8) | buf[firmware_info.file_size - 2];
+ inspect_fw_pchecksum("Firmware checksum", computed_checksum, file_checksum);
+
+ /* Verify checksum */
+ if (computed_checksum != file_checksum) {
+ ret = -1;
+ ERR("checksums do not match");
+ goto out_free_buf;
+ }
+
+ printf("\n");
+
+ if (extract) {
+ FILE *fp;
+ char *filename;
+
+ if (ofname == NULL) {
+ filename = malloc(strlen(firmware_info.file_name) + 10);
+ sprintf(filename, "%s-firmware", firmware_info.file_name);
+ } else {
+ filename = ofname;
+ }
+ printf("Extracting firmware to \"%s\"...\n", filename);
+ fp = fopen(filename, "wb");
+ if (fp) {
+ if (!fwrite(buf + sizeof (struct fw_header),
+ LE32_TO_HOST(hdr->firmware_len), 1, fp)) {
+ ERRS("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERRS("error in fopen(): %s", strerror(errno));
+ }
+ if (ofname == NULL) {
+ free(filename);
+ }
+ printf("\n");
+ }
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+/*
+ * Main entry point
+ */
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+
+ progname = basename(argv[0]);
+
+ int c;
+
+ while ((c = getopt(argc, argv, "B:H:F:f:o:ixh")) != -1) {
+ switch (c) {
+ case 'B':
+ board_id = optarg;
+ break;
+ case 'H':
+ opt_hw_id = optarg;
+ break;
+ case 'F':
+ layout_id = optarg;
+ break;
+ case 'f':
+ firmware_info.file_name = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'i':
+ inspect = 1;
+ break;
+ case 'x':
+ inspect = 1;
+ extract = 1;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret) {
+ goto out;
+ }
+ if (!inspect) {
+ ret = build_fw();
+ } else {
+ ret = inspect_fw();
+ }
+
+ out:
+ return ret;
+}
diff --git a/tools/firmware-utils/src/mkrtn56uimg.c b/tools/firmware-utils/src/mkrtn56uimg.c
new file mode 100644
index 0000000..fe9ae2c
--- /dev/null
+++ b/tools/firmware-utils/src/mkrtn56uimg.c
@@ -0,0 +1,294 @@
+/*
+ *
+ * Copyright (C) 2014 OpenWrt.org
+ * Copyright (C) 2014 Mikko Hissa <mikko.hissa@werzek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#define IH_MAGIC 0x27051956
+#define IH_NMLEN 32
+#define IH_PRODLEN 23
+
+#define IH_TYPE_INVALID 0
+#define IH_TYPE_STANDALONE 1
+#define IH_TYPE_KERNEL 2
+#define IH_TYPE_RAMDISK 3
+#define IH_TYPE_MULTI 4
+#define IH_TYPE_FIRMWARE 5
+#define IH_TYPE_SCRIPT 6
+#define IH_TYPE_FILESYSTEM 7
+
+/*
+ * Compression Types
+ */
+#define IH_COMP_NONE 0
+#define IH_COMP_GZIP 1
+#define IH_COMP_BZIP2 2
+#define IH_COMP_LZMA 3
+
+typedef struct {
+ uint8_t major;
+ uint8_t minor;
+} version_t;
+
+typedef struct {
+ version_t kernel;
+ version_t fs;
+ uint8_t productid[IH_PRODLEN];
+ uint8_t sub_fs;
+ uint32_t ih_ksz;
+} asus_t;
+
+typedef struct image_header {
+ uint32_t ih_magic;
+ uint32_t ih_hcrc;
+ uint32_t ih_time;
+ uint32_t ih_size;
+ uint32_t ih_load;
+ uint32_t ih_ep;
+ uint32_t ih_dcrc;
+ uint8_t ih_os;
+ uint8_t ih_arch;
+ uint8_t ih_type;
+ uint8_t ih_comp;
+ union {
+ uint8_t ih_name[IH_NMLEN];
+ asus_t asus;
+ } tail;
+} image_header_t;
+
+typedef struct squashfs_sb {
+ uint32_t s_magic;
+ uint32_t pad0[9];
+ uint64_t bytes_used;
+} squashfs_sb_t;
+
+typedef enum {
+ NONE, FACTORY, SYSUPGRADE,
+} op_mode_t;
+
+void
+calc_crc(image_header_t *hdr, void *data, uint32_t len)
+{
+ /*
+ * Calculate payload checksum
+ */
+ hdr->ih_dcrc = htonl(crc32(0, (Bytef *)data, len));
+ hdr->ih_size = htonl(len);
+ /*
+ * Calculate header checksum
+ */
+ hdr->ih_hcrc = 0;
+ hdr->ih_hcrc = htonl(crc32(0, (Bytef *)hdr, sizeof(image_header_t)));
+}
+
+
+static void
+usage(const char *progname, int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ int i;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream, "\n"
+ "Options:\n"
+ " -f <file> generate a factory flash image <file>\n"
+ " -s <file> generate a sysupgrade flash image <file>\n"
+ " -h show this screen\n");
+ exit(status);
+}
+
+int
+process_image(char *progname, char *filename, op_mode_t opmode)
+{
+ int fd, len;
+ void *data, *ptr;
+ char namebuf[IH_NMLEN];
+ struct stat sbuf;
+ uint32_t checksum, offset_kernel, offset_sqfs, offset_end,
+ offset_sec_header, offset_eb, offset_image_end;
+ squashfs_sb_t *sqs;
+ image_header_t *hdr;
+
+ if ((fd = open(filename, O_RDWR, 0666)) < 0) {
+ fprintf (stderr, "%s: Can't open %s: %s\n",
+ progname, filename, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ if (fstat(fd, &sbuf) < 0) {
+ fprintf (stderr, "%s: Can't stat %s: %s\n",
+ progname, filename, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ if ((unsigned)sbuf.st_size < sizeof(image_header_t)) {
+ fprintf (stderr,
+ "%s: Bad size: \"%s\" is no valid image\n",
+ progname, filename);
+ return (EXIT_FAILURE);
+ }
+
+ ptr = (void *)mmap(0, sbuf.st_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd, 0);
+
+ if ((caddr_t)ptr == (caddr_t)-1) {
+ fprintf (stderr, "%s: Can't read %s: %s\n",
+ progname, filename, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ hdr = ptr;
+
+ if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+ fprintf (stderr,
+ "%s: Bad Magic Number: \"%s\" is no valid image\n",
+ progname, filename);
+ return (EXIT_FAILURE);
+ }
+
+ if (opmode == FACTORY) {
+ strncpy(namebuf, hdr->tail.ih_name, IH_NMLEN);
+ hdr->tail.asus.kernel.major = 0;
+ hdr->tail.asus.kernel.minor = 0;
+ hdr->tail.asus.fs.major = 0;
+ hdr->tail.asus.fs.minor = 0;
+ strncpy((char *)&hdr->tail.asus.productid, "RT-N56U", IH_PRODLEN);
+ }
+
+ if (hdr->tail.asus.ih_ksz == 0)
+ hdr->tail.asus.ih_ksz = htonl(ntohl(hdr->ih_size) + sizeof(image_header_t));
+
+ offset_kernel = sizeof(image_header_t);
+ offset_sqfs = ntohl(hdr->tail.asus.ih_ksz);
+ sqs = ptr + offset_sqfs;
+ offset_sec_header = offset_sqfs + sqs->bytes_used;
+
+ /*
+ * Reserve space for the second header.
+ */
+ offset_end = offset_sec_header + sizeof(image_header_t);
+ offset_eb = ((offset_end>>16)+1)<<16;
+
+ if (opmode == FACTORY)
+ offset_image_end = offset_eb + 4;
+ else
+ offset_image_end = sbuf.st_size;
+ /*
+ * Move the second header at the end of the image.
+ */
+ offset_end = offset_sec_header;
+ offset_sec_header = offset_eb - sizeof(image_header_t);
+
+ /*
+ * Remove jffs2 markers between squashfs and eb boundary.
+ */
+ if (opmode == FACTORY)
+ memset(ptr+offset_end, 0xff ,offset_eb - offset_end);
+
+ /*
+ * Grow the image if needed.
+ */
+ if (offset_image_end > sbuf.st_size) {
+ (void) munmap((void *)ptr, sbuf.st_size);
+ ftruncate(fd, offset_image_end);
+ ptr = (void *)mmap(0, offset_image_end,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd, 0);
+ /*
+ * jffs2 marker
+ */
+ if (opmode == FACTORY) {
+ *(uint8_t *)(ptr+offset_image_end-4) = 0xde;
+ *(uint8_t *)(ptr+offset_image_end-3) = 0xad;
+ *(uint8_t *)(ptr+offset_image_end-2) = 0xc0;
+ *(uint8_t *)(ptr+offset_image_end-1) = 0xde;
+ }
+ }
+
+ /*
+ * Calculate checksums for the second header to be used after flashing.
+ */
+ if (opmode == FACTORY) {
+ hdr = ptr+offset_sec_header;
+ memcpy(hdr, ptr, sizeof(image_header_t));
+ strncpy(hdr->tail.ih_name, namebuf, IH_NMLEN);
+ calc_crc(hdr, ptr+offset_kernel, offset_sqfs - offset_kernel);
+ calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_image_end - offset_kernel);
+ } else {
+ calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_sqfs - offset_kernel);
+ }
+
+ if (sbuf.st_size > offset_image_end)
+ (void) munmap((void *)ptr, sbuf.st_size);
+ else
+ (void) munmap((void *)ptr, offset_image_end);
+
+ ftruncate(fd, offset_image_end);
+ (void) close (fd);
+
+ return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char **argv)
+{
+ int opt;
+ char *filename, *progname;
+ op_mode_t opmode = NONE;
+
+ progname = argv[0];
+
+ while ((opt = getopt(argc, argv,":s:f:h?")) != -1) {
+ switch (opt) {
+ case 's':
+ opmode = SYSUPGRADE;
+ filename = optarg;
+ break;
+ case 'f':
+ opmode = FACTORY;
+ filename = optarg;
+ break;
+ case 'h':
+ opmode = NONE;
+ default:
+ usage(progname, EXIT_FAILURE);
+ opmode = NONE;
+ }
+ }
+
+ if(filename == NULL)
+ opmode = NONE;
+
+ switch (opmode) {
+ case NONE:
+ usage(progname, EXIT_FAILURE);
+ break;
+ case FACTORY:
+ case SYSUPGRADE:
+ return process_image(progname, filename, opmode);
+ break;
+ }
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/tools/firmware-utils/src/mksenaofw.c b/tools/firmware-utils/src/mksenaofw.c
new file mode 100644
index 0000000..7ea58f5
--- /dev/null
+++ b/tools/firmware-utils/src/mksenaofw.c
@@ -0,0 +1,417 @@
+/*
+ *
+ * Copyright (C) 2012 OpenWrt.org
+ * Copyright (C) 2012 Mikko Hissa <mikko.hissa@uta.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include "md5.h"
+
+#define HDR_LEN 0x60
+#define BUF_SIZE 0x200
+#define VERSION_SIZE 0x10
+#define MD5_SIZE 0x10
+#define PAD_SIZE 0x20
+
+#define DEFAULT_BLOCK_SIZE 65535
+
+#define DEFAULT_HEAD_VALUE 0x0
+#define DEFAULT_VERSION "123"
+#define DEFAULT_MAGIC 0x12345678
+
+typedef struct {
+ uint32_t head;
+ uint32_t vendor_id;
+ uint32_t product_id;
+ uint8_t version[VERSION_SIZE];
+ uint32_t firmware_type;
+ uint32_t filesize;
+ uint32_t zero;
+ uint8_t md5sum[MD5_SIZE];
+ uint8_t pad[PAD_SIZE];
+ uint32_t chksum;
+ uint32_t magic;
+} img_header;
+
+typedef struct {
+ uint8_t id;
+ char * name;
+} firmware_type;
+
+typedef enum {
+ NONE, ENCODE, DECODE
+} op_mode;
+
+static firmware_type FIRMWARE_TYPES[] = {
+ { 0x01, "bootloader" },
+ { 0x02, "kernel" },
+ { 0x03, "kernelapp" },
+ { 0x04, "apps" },
+ /* The types below this line vary by manufacturer */
+ { 0x05, "littleapps (D-Link)/factoryapps (EnGenius)" },
+ { 0x06, "sounds (D-Link)/littleapps (EnGenius)" },
+ { 0x07, "userconfig (D-Link)/appdata (EnGenius)" },
+ { 0x08, "userconfig (EnGenius)"},
+ { 0x09, "odmapps (EnGenius)"},
+ { 0x0a, "factoryapps (D-Link)" },
+ { 0x0b, "odmapps (D-Link)" },
+ { 0x0c, "langpack (D-Link)" }
+};
+
+static long get_file_size(const char *filename)
+{
+ FILE *fp_file;
+ long result;
+
+ fp_file = fopen(filename, "r");
+ if (!fp_file)
+ return -1;
+ fseek(fp_file, 0, SEEK_END);
+ result = ftell(fp_file);
+ fclose(fp_file);
+ return result;
+}
+
+static int header_checksum(void *data, int len)
+{
+ int i;
+ int sum;
+
+ sum = 0;
+ if (data != NULL && len >= 0) {
+ for (i = 0; i < len; ++i)
+ sum += *(unsigned char *) (data + i);
+ return sum;
+ }
+
+ return -1;
+}
+
+static int md5_file(const char *filename, uint8_t *dst)
+{
+ FILE *fp_src;
+ MD5_CTX ctx;
+ char buf[BUF_SIZE];
+ size_t bytes_read;
+
+ MD5_Init(&ctx);
+
+ fp_src = fopen(filename, "r+b");
+ if (!fp_src) {
+ return -1;
+ }
+ while (!feof(fp_src)) {
+ bytes_read = fread(&buf, 1, BUF_SIZE, fp_src);
+ MD5_Update(&ctx, &buf, bytes_read);
+ }
+ fclose(fp_src);
+
+ MD5_Final(dst, &ctx);
+
+ return 0;
+}
+
+static int encode_image(const char *input_file_name,
+ const char *output_file_name, img_header *header, int block_size)
+{
+ char buf[BUF_SIZE];
+ size_t bytes_read;
+ size_t pad_len = 0;
+ size_t bytes_avail;
+
+ FILE *fp_input;
+ FILE *fp_output;
+
+ int i;
+ long magic;
+
+ fp_input = fopen(input_file_name, "r+b");
+ if (!fp_input) {
+ fprintf(stderr, "Cannot open %s !!\n", input_file_name);
+ return -1;
+ }
+
+ fp_output = fopen(output_file_name, "w+b");
+ if (!fp_output) {
+ fprintf(stderr, "Cannot open %s !!\n", output_file_name);
+ fclose(fp_input);
+ return -1;
+ }
+
+ header->filesize = get_file_size(input_file_name);
+ if (!header->filesize) {
+ fprintf(stderr, "File %s open/size error!\n", input_file_name);
+ fclose(fp_input);
+ fclose(fp_output);
+ return -1;
+ }
+ /*
+ * Zero padding
+ */
+ if (block_size > 0) {
+ pad_len = block_size - (header->filesize % block_size);
+ }
+
+ if (md5_file(input_file_name, (uint8_t *) &header->md5sum) < 0) {
+ fprintf(stderr, "MD5 failed on file %s\n", input_file_name);
+ fclose(fp_input);
+ fclose(fp_output);
+ return -1;
+ }
+ header->zero = 0;
+ header->chksum = header_checksum(header, HDR_LEN);
+ header->head = htonl(header->head);
+ header->vendor_id = htonl(header->vendor_id);
+ header->product_id = htonl(header->product_id);
+ header->firmware_type = htonl(header->firmware_type);
+ header->filesize = htonl(header->filesize);
+ header->chksum = htonl(header->chksum);
+ magic = header->magic;
+ header->magic = htonl(header->magic);
+
+ fwrite(header, HDR_LEN, 1, fp_output);
+
+ while (!feof(fp_input) || pad_len > 0) {
+
+ if (!feof(fp_input))
+ bytes_read = fread(&buf, 1, BUF_SIZE, fp_input);
+ else
+ bytes_read = 0;
+
+ /*
+ * No more bytes read, start padding
+ */
+ if (bytes_read < BUF_SIZE && pad_len > 0) {
+ bytes_avail = BUF_SIZE - bytes_read;
+ memset( &buf[bytes_read], 0, bytes_avail);
+ bytes_read += bytes_avail < pad_len ? bytes_avail : pad_len;
+ pad_len -= bytes_avail < pad_len ? bytes_avail : pad_len;
+ }
+
+ for (i = 0; i < bytes_read; i++)
+ buf[i] ^= magic >> (i % 8) & 0xff;
+ fwrite(&buf, bytes_read, 1, fp_output);
+ }
+
+ fclose(fp_input);
+ fclose(fp_output);
+ return 1;
+}
+
+int decode_image(const char *input_file_name, const char *output_file_name)
+{
+ img_header header;
+ char buf[BUF_SIZE];
+
+ FILE *fp_input;
+ FILE *fp_output;
+ unsigned int i;
+
+ size_t bytes_read;
+ size_t bytes_written;
+
+ fp_input = fopen(input_file_name, "r+b");
+ if (!fp_input) {
+ fprintf(stderr, "Cannot open %s !!\n", input_file_name);
+ fclose(fp_input);
+ return -1;
+ }
+
+ fp_output = fopen(output_file_name, "w+b");
+ if (!fp_output) {
+ fprintf(stderr, "Cannot open %s !!\n", output_file_name);
+ fclose(fp_output);
+ return -1;
+ }
+
+ if (fread(&header, 1, HDR_LEN, fp_input) != HDR_LEN) {
+ fprintf(stderr, "Incorrect header size!!");
+ fclose(fp_input);
+ fclose(fp_output);
+ return -1;
+ }
+
+ header.head = ntohl(header.head);
+ header.vendor_id = ntohl(header.vendor_id);
+ header.product_id = ntohl(header.product_id);
+ header.firmware_type = ntohl(header.firmware_type);
+ header.filesize = ntohl(header.filesize);
+ header.chksum = ntohl(header.chksum);
+ header.magic = ntohl(header.magic);
+
+ bytes_written = 0;
+ while (!feof(fp_input)) {
+
+ bytes_read = fread(&buf, 1, BUF_SIZE, fp_input);
+ for (i = 0; i < bytes_read; i++)
+ buf[i] ^= header.magic >> (i % 8) & 0xff;
+
+ /*
+ * Handle padded source file
+ */
+ if (bytes_written + bytes_read > header.filesize) {
+ bytes_read = header.filesize - bytes_written;
+ if (bytes_read > 0)
+ fwrite(&buf, bytes_read, 1, fp_output);
+ break;
+ }
+
+ fwrite(&buf, bytes_read, 1, fp_output);
+ bytes_written += bytes_read;
+ }
+
+ fclose(fp_input);
+ fclose(fp_output);
+
+ return 1;
+}
+
+static void usage(const char *progname, int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ int i;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream, "\n"
+ "Options:\n"
+ " -e <file> encode image file <file>\n"
+ " -d <file> decode image file <file>\n"
+ " -o <file> write output to the file <file>\n"
+ " -t <type> set image type to <type>\n"
+ " valid image <type> values:\n");
+ for (i = 0; i < sizeof(FIRMWARE_TYPES) / sizeof(firmware_type); i++) {
+ fprintf(stream, " %-5i= %s\n", FIRMWARE_TYPES[i].id,
+ FIRMWARE_TYPES[i].name);
+ }
+ fprintf(stream, " -v <version> set image version to <version>\n"
+ " -r <vendor> set image vendor id to <vendor>\n"
+ " -p <product> set image product id to <product>\n"
+ " -m <magic> set encoding magic <magic>\n"
+ " -z enable image padding to <blocksize>\n"
+ " -b <blocksize> set image <blocksize>, defaults to %u\n"
+ " -h show this screen\n", DEFAULT_BLOCK_SIZE);
+ exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ char *input_file, *output_file, *progname = NULL;
+ op_mode mode = NONE;
+ int tmp, i, pad = 0;
+ int block_size;
+ img_header header;
+
+ block_size = DEFAULT_BLOCK_SIZE;
+ progname = basename(argv[0]);
+
+ memset(&header, 0, sizeof( img_header ));
+ header.magic = DEFAULT_MAGIC;
+ header.head = DEFAULT_HEAD_VALUE;
+ strncpy( (char*)&header.version, DEFAULT_VERSION, VERSION_SIZE - 1);
+
+ while ((opt = getopt(argc, argv, ":o:e:d:t:v:r:p:m:b:h?z")) != -1) {
+ switch (opt) {
+ case 'e':
+ input_file = optarg;
+ mode = ENCODE;
+ break;
+ case 'd':
+ input_file = optarg;
+ mode = DECODE;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ case 't':
+ tmp = strtol(optarg, 0, 10);
+ for (i = 0; i < sizeof(FIRMWARE_TYPES) / sizeof(firmware_type);
+ i++) {
+ if (FIRMWARE_TYPES[i].id == tmp) {
+ header.firmware_type = FIRMWARE_TYPES[i].id;
+ break;
+ }
+ }
+ if (header.firmware_type == 0) {
+ fprintf(stderr, "Invalid firmware type \"0\"!\n");
+ usage(progname, EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ strncpy( (char*)&header.version, optarg,
+ VERSION_SIZE - 1);
+ break;
+ case 'r':
+ header.vendor_id = strtol(optarg, 0, 0);
+ break;
+ case 'p':
+ header.product_id = strtol(optarg, 0, 0);
+ break;
+ case 'm':
+ header.magic = strtoul(optarg, 0, 16);
+ break;
+ case 'z':
+ pad = 1;
+ break;
+ case 'b':
+ block_size = strtol(optarg, 0, 10);
+ break;
+ case 'h':
+ usage(progname, EXIT_SUCCESS);
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ usage(progname, EXIT_FAILURE);
+ break;
+ case '?':
+ fprintf(stderr, "Unrecognized option: -%c\n", optopt);
+ usage(progname, EXIT_FAILURE);
+ break;
+ default:
+ usage(progname, EXIT_FAILURE);
+ break;
+ }
+ }
+
+ /* Check required arguments*/
+ if (header.firmware_type == 0) {
+ fprintf(stderr, "Firmware type must be defined\n");
+ usage(progname, EXIT_FAILURE);
+ } else if (input_file == 0 || output_file == 0) {
+ fprintf(stderr, "Input and output files must be defined\n");
+ usage(progname, EXIT_FAILURE);
+ } else if (header.vendor_id == 0 || header.product_id == 0) {
+ fprintf(stderr, "Vendor ID and Product ID must be defined and non-zero\n");
+ usage(progname, EXIT_FAILURE);
+ }
+
+ switch (mode) {
+ case NONE:
+ fprintf(stderr, "A mode must be defined\n");
+ usage(progname, EXIT_FAILURE);
+ break;
+ case ENCODE:
+ if (encode_image(input_file, output_file, &header, pad ? block_size : 0)
+ < 0)
+ return EXIT_FAILURE;
+ break;
+ case DECODE:
+ if (decode_image(input_file, output_file) < 0)
+ return EXIT_FAILURE;
+ break;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/mktitanimg.c b/tools/firmware-utils/src/mktitanimg.c
new file mode 100644
index 0000000..cca4a0e
--- /dev/null
+++ b/tools/firmware-utils/src/mktitanimg.c
@@ -0,0 +1,1040 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include "mktitanimg.h"
+
+
+struct checksumrecord
+{
+ unsigned int magic;
+ unsigned int chksum; /* The checksum for the complete header.
+ Excepting the
+ checksum block */
+};
+/***************************************************************************
+ * void print_help(void)
+ ***************************************************************************/
+void print_help(void)
+{
+ static char* help_page[]=
+ {
+ "mknspimg version 1.0, Texas Instruments, 2004",
+ "Syntax:",
+ " mknspimg -o outfile -i image1 image2 -a align1 align2 [-v] [-b] [-p prod_id] [-r rel_id] [-s rel_name] [-f flags]",
+ "Example:",
+ " mknspimg -o nsp_image.bin -i kernel.bin files.img -a 0 4096",
+ "This generates 'nsp_image.bin' from two input files aligning first to 0 and second to 4096 bytes."
+ };
+
+ int num_lines = sizeof(help_page)/sizeof(char*);
+ int i;
+ for(i=0; i < num_lines; i++) {
+ printf("%s\n", help_page[i]);
+ }
+}
+
+/***************************************************************************
+ * void mknspimg_print_hdr(NSP_IMG_HDR* p_img_hdr)
+ ***************************************************************************/
+void mknspimg_print_hdr(struct nsp_img_hdr *hdr)
+{
+ struct nsp_img_hdr_chksum *chksum;
+ struct nsp_img_hdr_section_info *sect_info;
+ struct nsp_img_hdr_sections *section;
+ int i;
+
+ printf("****************** NSP Image Summary ******************\n");
+ printf("Magic: 0x%x\n", hdr->head.magic);
+ printf("Image Header Size: 0x%x bytes\n", hdr->head.hdr_size);
+ printf("Total Image Size: %d bytes\n", hdr->head.image_size);
+ printf("Product ID: 0x%x\n", hdr->head.prod_id);
+ printf("Release ID: 0x%x\n", hdr->head.rel_id);
+ printf("Version ID: 0x%x\n", hdr->head.version);
+
+ printf("Offset Info: 0x%x\n", hdr->head.info_offset);
+ printf("Offset Sect info: 0x%x\n", hdr->head.sect_info_offset);
+ printf("Offset Sections: 0x%x\n", hdr->sect_info.sections_offset);
+
+ chksum=(struct nsp_img_hdr_chksum *)(hdr+hdr->head.chksum_offset);
+ printf("Header Checksum: 0x%x\n", chksum->hdr_chksum);
+
+ printf("+++ Section Information +++\n");
+ printf("# of sections: %u\n", hdr->sect_info.num_sects);
+ section=&(hdr->sections);
+ for(i = 0; i < hdr->sect_info.num_sects; i++, section++) {
+ printf("+++++ Section %d +++++\n", i);
+ printf("Total size: %u bytes\n", section->total_size);
+ printf("Raw Size: %u bytes\n", section->raw_size);
+ printf("Offset: 0x%x\n", section->offset);
+ printf("Type: 0x%x\n", section->type);
+ printf("Name: %s\n", section->name);
+ }
+ printf("*******************************************************\n");
+}
+
+CMDLINE_CFG cmd_line_cfg =
+{
+ {
+ /* MIN MAX FLAGS OPTION */
+ { 2, 2, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-a' align1 align2 */
+ { 0, 0, CMDLINE_OPTFLAG_ALLOW }, /* '-b' bootstrap */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-c' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-d' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-e' */
+ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-f' flags */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-g' */
+ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-h' */
+ { 2, 2, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-i arg1 arg2 ' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-j' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-k' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-l' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-m' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-n' */
+ { 1, 1, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-o arg' */
+ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-p' PROD_ID */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-q' */
+ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-r' REL_ID */
+ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-s' "Release XXX.XXX" */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-t' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-u' */
+ { 0, 0, CMDLINE_OPTFLAG_ALLOW }, /* '-v' control VERBOSE/NON-VERBOSE mode */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-w' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-x' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-y' */
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW } /* '-z' */
+ },
+ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* global arguments */
+};
+
+/***************************************************************************
+ * int nsp_img_write(void* image, char* file, int padding)
+ * Write out the image.
+ ***************************************************************************/
+int main(int argc, char* argv[], char* env[])
+{
+ FILE* nsp_image = NULL;
+ int header_version=1;
+ int cmdline_err;
+ char* cmdline_error_msg;
+
+ char* filen_kernel;
+ char* filen_files;
+ char* filen_out;
+
+ int i,count; /* loop variables */
+ int num_sects = 2; /* We require exactly two image with -i option
+ (see CMDLINE_CFG structure above) */
+ int desc_count=0;
+ int total = 0;
+
+ int header_size=0;
+ struct nsp_img_hdr_head *img_hdr_head; /* Start of image header */
+ struct nsp_img_hdr_info *img_hdr_info;
+ struct nsp_img_hdr_section_info *img_hdr_section_info ;
+ struct nsp_img_hdr_sections *img_hdr_sections, *section; /* Section pointers */
+
+
+ /* Configure the command line. */
+ cmdline_configure(&cmd_line_cfg);
+
+ /* Read and parse the command line. */
+ cmdline_err = cmdline_read(argc, argv);
+
+ /* Check for parsing errors. */
+ if(cmdline_err != 0) {
+ /* Get the parse error message */
+ cmdline_error_msg = cmdline_error(cmdline_err);
+
+ /* Print it out */
+ printf("%s\n", cmdline_error_msg);
+
+ /* Print our help too */
+ print_help();
+ return -1;
+ }
+ if(cmdline_getopt_count('h') > 0)
+ {
+ header_version=atoi(argv[cmdline_getarg(cmdline_getarg_list('h'),0)]);
+ }
+ /* Set up arguments */
+ filen_kernel = argv[cmdline_getarg(cmdline_getarg_list('i'),0)];
+ filen_files = argv[cmdline_getarg(cmdline_getarg_list('i'),1)];
+ filen_out = argv[cmdline_getarg(cmdline_getarg_list('o'),0)];
+ /* Command line arguments have been parsed. Start doing our work. */
+
+ /* Caculate the header size, and allocate the memory, and assign the sub pointers */
+ header_size = sizeof(struct nsp_img_hdr_head) + /* This has a single section
+ desc block already */
+ (header_version==1?0:4) +
+ sizeof(struct nsp_img_hdr_info) +
+ sizeof(struct nsp_img_hdr_section_info) +
+ sizeof(struct nsp_img_hdr_sections) * num_sects ;
+
+ img_hdr_head = (struct nsp_img_hdr_head *)malloc(header_size);
+ memset(img_hdr_head, 0x0, header_size);
+ img_hdr_info = (struct nsp_img_hdr_info*)((char *)img_hdr_head + sizeof(struct nsp_img_hdr_head) + (header_version==1?0:4));
+ img_hdr_section_info = (struct nsp_img_hdr_section_info*)((char *)img_hdr_info + sizeof(struct nsp_img_hdr_info));
+ img_hdr_sections = (struct nsp_img_hdr_sections*)((char *)img_hdr_section_info + sizeof(struct nsp_img_hdr_section_info));
+ section = img_hdr_sections;
+ memset(img_hdr_head, 0xff, (void*)img_hdr_info - (void*)img_hdr_head);
+
+ img_hdr_head->hdr_version = header_version;
+ img_hdr_head->hdr_size = header_size;
+ img_hdr_head->info_offset = (void*)img_hdr_info - (void*)img_hdr_head;
+ img_hdr_head->sect_info_offset = (void*)img_hdr_section_info - (void*)img_hdr_head;
+
+ img_hdr_section_info->num_sects = num_sects;
+ img_hdr_section_info->sect_size = sizeof(struct nsp_img_hdr_sections);
+ img_hdr_section_info->sections_offset = (void*)img_hdr_sections - (void*)img_hdr_head;
+
+/* chksum = (struct nsp_img_hdr_chksum *)
+ ((unsigned int)image_hdr + header_size - sizeof(struct nsp_img_hdr_chksum));*/
+
+ /* Open the out file */
+ nsp_image = fopen(filen_out,"wb+");
+ if(nsp_image==NULL) {
+ printf("ERROR: can't open %s for writing.\n", filen_out);
+ return -1;
+ }
+
+ /* Skip image header. We'll come back to it after we've written out the images. */
+ fseek(nsp_image,header_size,SEEK_SET);
+ total = ftell(nsp_image);
+ total = header_size;
+ printf("total=%x\n",total);
+ {
+ int align;
+ int padding;
+ char * buf;
+ align = (header_version==1?0x10000:0x4000);
+ if(align==0) {
+ /* The user indicated no padding */
+ padding = 0;
+ } else {
+ /* Calculate number padding bytes */
+ if((total %align) ==0)
+ padding=0;
+ else
+ padding = align - (total % align);
+ }
+ if(padding>0)
+ {
+ buf=malloc(padding);
+ memset(buf, 0xff, padding);
+ if(fwrite((void*)buf,1,padding,nsp_image)!=padding) {
+ printf("ERROR: can't write to %s.\n", filen_out);
+ free(buf);
+ return -1;
+ }
+ free(buf);
+
+ }
+ total+=padding;
+
+
+ }
+ /* Write out all specified images (with -i option) */
+ for(i=0; i < num_sects; i++) {
+ char* file_name; /* input file name */
+ FILE* filep; /* input file pointer */
+ int padding; /* number of padding bytes to prepend */
+ int align; /* align factor from command line */
+ int result; /* intermediate result */
+ char * buf;
+
+ /* Open the specified image for reading */
+ file_name = argv[cmdline_getarg(cmdline_getarg_list('i'),i)];
+ filep = fopen(file_name, "rb");
+ if(filep==NULL) {
+ printf("ERROR: can't open file %s for reading.\n", file_name);
+ return -1;
+ }
+ section->flags = ~0x00;
+ /* Determine file size */
+ fseek(filep,0,SEEK_END);
+ section->raw_size=ftell(filep);
+ fseek(filep,0,SEEK_SET);
+ cs_calc_sum(filep,(unsigned long *)&section->chksum,0);
+ fseek(filep,0,SEEK_SET);
+
+ /* Retrieve the alignment constant */
+ /* Set image offset from the beginning of the out file */
+ section->offset=total;// + padding;
+
+ //total += padding;
+
+ /* Copy the image file into nsp_image */
+ count = section->raw_size;
+ buf=malloc(count);
+ result=fread(buf, 1, count, filep);
+ fwrite(buf, 1, result, nsp_image);
+ free(buf);
+
+ /* HACK: This is a hack to get the names and types to the files.
+ TODO: Fix this to be a real method */
+ if(i==0){
+ section->type=NSP_IMG_SECTION_TYPE_KERNEL;
+ strncpy(section->name, "kernel", 16);
+ } else if(i==1){
+ section->type=NSP_IMG_SECTION_TYPE_FILESYSTEM_ROOT;
+ strncpy(section->name, "root", 16);
+ }
+
+ /* Account for the total */
+ align = strtoul(argv[cmdline_getarg(cmdline_getarg_list('a'),i)],NULL,0);
+ if(i==0){
+ if(align==0 || (((section->raw_size+ section->offset)%align)==0))
+ padding=0;
+ else
+ padding = align - ((section->raw_size+ section->offset) % align);
+
+ section->total_size=section->raw_size + padding;
+ }
+ else{
+ #define EXTRA_BLOCK 0x10000
+ unsigned int squash_padding;
+ squash_padding = EXTRA_BLOCK - section->raw_size % EXTRA_BLOCK;
+ buf=malloc(EXTRA_BLOCK + 4);
+ memset(buf, 0, squash_padding);
+ fwrite(buf, 1, squash_padding, nsp_image);
+ memset(buf, 0, EXTRA_BLOCK + 4);
+ *((unsigned int *)buf)=0xdec0adde;
+ *((unsigned int *)(buf+EXTRA_BLOCK))=0xdec0adde;
+ fwrite(buf, 1, EXTRA_BLOCK+4, nsp_image);
+ free(buf);
+
+ if(align==0 || (((section->raw_size + (EXTRA_BLOCK + 4 + squash_padding)) %align)==0))
+ padding=0;
+ else
+ padding = align - ((section->raw_size + (EXTRA_BLOCK + 4 + squash_padding)) % align);
+ section->total_size=section->raw_size + (EXTRA_BLOCK + 4 + squash_padding) + padding;
+ }
+ if(padding>0){
+ buf=malloc(padding);
+ memset(buf, 0xff, padding);
+ fwrite(buf, 1, padding, nsp_image);
+ free(buf);
+ }
+ printf("*****padding is %d\ttotal_size=%d\traw_size=%d\n",padding, section->total_size, section->raw_size);
+
+ //total += section->raw_size;
+ total = section->total_size + section->offset;
+ printf("total=0x%x\n",total);
+ /* Close the input file */
+ fclose(filep);
+
+ /* Move the section pointer to the next slot */
+ section++;
+ }
+
+ /* Take care of the NSP image header fields */
+
+ /* head fields */
+ img_hdr_head->magic = NSP_IMG_MAGIC_NUMBER;
+ img_hdr_head->boot_offset = img_hdr_sections->offset;
+ img_hdr_head->flags = ~0x00; /* Set to all 1's */
+
+ if(cmdline_getopt_count('b'))
+ img_hdr_head->flags &= ~(NSP_IMG_FLAG_FAILBACK_5 | NSP_IMG_FLAG_FAILBACK_1);
+
+ if(cmdline_getopt_count('f'))
+ img_hdr_head->flags = strtoul(argv[cmdline_getarg(cmdline_getarg_list('f'),0)], 0, 16);
+
+#if 0
+ img_hdr_head->hdr_version = 2;
+ img_hdr_head->hdr_size = header_size;
+#endif
+
+ if(cmdline_getopt_count('p'))
+ img_hdr_head->prod_id = strtoul(argv[cmdline_getarg(cmdline_getarg_list('p'),0)], 0, 16);
+ else
+ img_hdr_head->prod_id = 0x4C575943;
+
+ if(cmdline_getopt_count('r'))
+ img_hdr_head->rel_id = strtoul(argv[cmdline_getarg(cmdline_getarg_list('r'),0)], 0, 0);
+ else
+ img_hdr_head->rel_id = 0x10203040;
+
+ if(cmdline_getopt_count('s'))
+ img_hdr_head->version = strtoul(argv[cmdline_getarg(cmdline_getarg_list('s'),0)], 0, 0);
+ else
+ img_hdr_head->version = 0x0b040000;
+ img_hdr_head->image_size = total;
+#if 0
+ img_hdr_head->info_offset = (unsigned int)(&(image_hdr->info)) -
+ (unsigned int)image_hdr;
+ img_hdr_head->sect_info_offset= (unsigned int)(&(image_hdr->sect_info)) -
+ (unsigned int)image_hdr;
+#endif
+// image_hdr->head.chksum_offset = (unsigned int)chksum - (unsigned int)image_hdr;
+ img_hdr_head->chksum_offset = 0xffffffff;
+// image_hdr->head.pad1 = 0xffffffff;
+ /* info fields */
+ /* TODO: Fix. Do nothing yet */
+// strncpy(nsp_img_hdr.id.prod_info,NSP_PRODINFO_STRING,sizeof(NSP_PRODINFO_STRING));
+ strcpy(img_hdr_info->image_filename, (const char *)basename(filen_out));
+ /* section fields */
+#if 0
+ img_hdr_section_info->num_sects= num_sects;
+ img_hdr_section_info->sect_size= sizeof(struct nsp_img_hdr_sections);
+ img_hdr_section_info->sections_offset= (unsigned int)(&(image_hdr->sections)) -
+ (unsigned int)image_hdr;
+#endif
+
+ /* Calculate checksum(s) */
+#if 0
+ chksum->hdr_chksum = cs_calc_buf_sum((char*)image_hdr,
+ header_size - sizeof(struct nsp_img_hdr_chksum));
+#endif
+ /* Write out the NSP header. */
+ fseek(nsp_image,0,SEEK_SET);
+ count = fwrite((void*)img_hdr_head, header_size, 1, nsp_image);
+ if(count!=1) {
+ printf("ERROR: can't write to %s.\n", filen_out);
+ return -1;
+ }
+
+ /* Check if -v option was specified (no arg needed) */
+ if(cmdline_getopt_count('v') > 0)
+ {
+ struct nsp_img_hdr_head head;
+ struct nsp_img_hdr *hdr;
+
+ /* Rewind the file back to the beginning */
+ fseek(nsp_image,0,SEEK_SET);
+
+ /* Read header from the file */
+ fread((void*)&head, sizeof(struct nsp_img_hdr_head),
+ 1, nsp_image);
+
+ /* Get memory to store the complete header */
+ hdr = (struct nsp_img_hdr *)malloc(head.hdr_size);
+
+ /* Read header from the file */
+ fseek(nsp_image,0,SEEK_SET);
+ fread((void*)hdr, head.hdr_size, 1, nsp_image);
+
+ /* Print it out */
+ mknspimg_print_hdr(hdr);
+ printf("Generated total %d bytes\n",total);
+ free(hdr);
+ }
+
+ free(img_hdr_head);
+
+ {
+ struct checksumrecord cr;
+ cr.magic=CKSUM_MAGIC_NUMBER;
+ cs_calc_sum(nsp_image, (unsigned long *)&cr.chksum, 0);
+ fseek(nsp_image,0, SEEK_END);
+ fwrite(&cr, 1, sizeof(cr), nsp_image);
+ }
+ {
+ FILE * non_web;
+ char fname[256];
+ char * img_buf;
+ unsigned int len;
+ strcpy(fname, filen_out);
+ strcat(fname, ".non_web");
+ non_web = fopen(fname,"wb+");
+ fseek(nsp_image, 0, SEEK_END);
+ len = ftell(nsp_image);
+ img_buf=malloc(len);
+ fseek(nsp_image, 0, SEEK_SET);
+ fread(img_buf, 1, len, nsp_image);
+ img_buf[0xb] = 0x17;
+ fwrite(img_buf, 1, len-sizeof(struct checksumrecord), non_web);
+ fclose(non_web);
+ free(img_buf);
+ }
+ /* Close NSP image file */
+ fclose(nsp_image);
+
+ /* return result */
+ return(0);
+}
+
+#ifdef DMALLOC
+#include <dmalloc.h>
+#endif /* DMALLOC */
+
+#define BUFLEN (1 << 16)
+
+static unsigned long crctab[256] =
+{
+ 0x0,
+ 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
+ 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
+ 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
+ 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
+ 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
+ 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
+ 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
+ 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
+ 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
+ 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
+ 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
+ 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
+ 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
+ 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
+ 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
+ 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
+ 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
+ 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
+ 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
+ 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
+ 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
+ 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
+ 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
+ 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
+ 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
+ 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
+ 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
+ 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
+ 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
+ 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
+ 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
+ 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
+ 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
+ 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
+ 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
+ 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
+ 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
+ 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
+ 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
+ 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
+ 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
+ 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
+ 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
+ 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
+ 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
+ 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
+ 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
+ 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
+ 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
+ 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
+ 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
+};
+
+int cs_is_tagged(FILE *fp)
+{
+ char buf[8];
+
+ fseek(fp, -8, SEEK_END);
+ fread(buf, 8, 1, fp);
+ if(*(unsigned long*)buf == CKSUM_MAGIC_NUMBER)
+ return 1;
+ return 0;
+}
+
+unsigned long cs_read_sum(FILE *fp)
+{
+ char buf[8];
+
+ fseek(fp, -8, SEEK_END);
+ fread(buf, 8, 1, fp);
+ return *((unsigned long*)&buf[4]);
+}
+
+int cs_calc_sum(FILE *fp, unsigned long *res, int tagged)
+{
+ unsigned char buf[BUFLEN];
+ unsigned long crc = 0;
+ uintmax_t length = 0;
+ size_t bytes_read;
+
+ fseek(fp, 0, SEEK_SET);
+
+ while((bytes_read = fread(buf, 1, BUFLEN, fp)) > 0)
+ {
+ unsigned char *cp = buf;
+
+ if(length + bytes_read < length)
+ return 0;
+
+ if(bytes_read != BUFLEN && tagged)
+ bytes_read -= 8;
+
+ length += bytes_read;
+ while(bytes_read--)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
+ }
+
+ if(ferror(fp))
+ return 0;
+
+ for(; length; length >>= 8)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
+
+ crc = ~crc & 0xFFFFFFFF;
+
+ *res = crc;
+
+ return 1;
+}
+
+unsigned long cs_calc_buf_sum(char *buf, int size)
+{
+ unsigned long crc = 0;
+ char *cp = buf;
+ unsigned long length = size;
+
+ while(size--)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
+
+ for(; length; length >>= 8)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
+
+ crc = ~crc & 0xFFFFFFFF;
+
+ return crc;
+}
+
+unsigned long cs_calc_buf_sum_ds(char *buf, int buf_size, char *sign, int sign_len)
+{
+ unsigned long crc = 0;
+ char *cp = buf;
+ unsigned long length = buf_size+sign_len;
+
+ while(buf_size--)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
+
+ cp = sign;
+ while(sign_len--)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
+
+
+ for(; length; length >>= 8)
+ crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
+
+ crc = ~crc & 0xFFFFFFFF;
+
+ return crc;
+}
+
+int cs_set_sum(FILE *fp, unsigned long sum, int tagged)
+{
+ unsigned long magic = CKSUM_MAGIC_NUMBER;
+
+ if(tagged)
+ fseek(fp, -8, SEEK_END);
+ else
+ fseek(fp, 0, SEEK_END);
+
+ if(fwrite(&magic, 1, 4, fp) < 4)
+ return 0;
+ if(fwrite(&sum, 1, 4, fp) < 4)
+ return 0;
+
+ return 1;
+}
+
+void cs_get_sum(FILE *fp, unsigned long *sum)
+{
+ unsigned long magic = 0;
+
+ fseek(fp, -8, SEEK_END);
+
+ fread(&magic, 4, 1, fp);
+ fread(sum, 4, 1, fp);
+}
+
+int cs_validate_file(char *filename)
+{
+ FILE *pFile = NULL;
+ unsigned long sum = 0, res = 0;
+
+ if((pFile = fopen(filename, "r")) == NULL)
+ return 0;
+
+ if(!cs_is_tagged(pFile))
+ {
+ fclose(pFile);
+ return 0;
+ }
+ if(!cs_calc_sum(pFile, &sum, 1))
+ {
+ fclose(pFile);
+ return 0;
+ }
+ cs_get_sum(pFile, &res);
+ fclose(pFile);
+
+ if(sum != res)
+ return 0;
+ return 1;
+}
+
+/* ********* Library internal data ********* */
+#define CMDLINE_TRUE 1
+#define CMDLINE_FALSE 0
+
+typedef enum CMDLINE_ERR
+{
+ CMDLINE_ERR_OK = 0, /* No Error (OK) */
+ CMDLINE_ERR_ERROR = -1, /* Unspecified error */
+ CMDLINE_ERR_INVKEY = -3, /* Invalid option key */
+ CMDLINE_ERR_MANYARG = -4, /* Too many arguments */
+ CMDLINE_ERR_FEWARG = -5, /* Too few arguments */
+ CMDLINE_ERR_ILLOPT = -6, /* Option not allowed (illegal option) */
+ CMDLINE_ERR_NOMEM = -7, /* No memory */
+ CMDLINE_ERR_OPTMIS = -8 /* A mandatory option is missing */
+} CMDLINE_ERR;
+
+/* Argument list */
+typedef struct CMDLINE_ARG
+{
+ int index; /* Index of the argument in the command line */
+ struct CMDLINE_ARG* p_next; /* Next node in the linked list */
+} CMDLINE_ARG;
+
+/* Master control block for an option */
+typedef struct CMDLINE_ARGS
+{
+ int argc; /* Total count of arguments found */
+ int optc; /* Total count of options found */
+ CMDLINE_ARG* list; /* Argument list */
+} CMDLINE_ARGS;
+
+/* Master control block for all found arguments */
+typedef struct CMDLINE_DATA
+{
+ CMDLINE_ARGS opt_args[26]; /* Array of MCBs for each option ('a' through 'z') */
+ CMDLINE_ARGS glb_args; /* Global arguments */
+ int parsed; /* Internal flag to prevent client calls if library is not initialized */
+} CMDLINE_DATA;
+
+/* ********* Local Data ********* */
+static CMDLINE_CFG cmdline_cfg;
+static CMDLINE_DATA cmdline_data;
+
+char* cmdline_errmsg = "CMDLINE ERROR";
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+void* cmdline_getarg_list(char opt)
+{
+ int index = (opt - 'a');
+
+ /* Check the validity of the index */
+ if((index < 0) || (index > 25))
+ {
+ /* ERROR: Wrong option */
+ return NULL;
+ }
+
+ /* Return a pointer to the ARGS control structure */
+ return((void*)(&cmdline_data.opt_args[index]));
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+int cmdline_getarg_count(void* list)
+{
+ CMDLINE_ARGS* p_args = (CMDLINE_ARGS*)list;
+
+ /* Return number of arguments for this option */
+ return(p_args->argc);
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+int cmdline_getopt_count(char opt)
+{
+ int index;
+
+ /* Calculate index value */
+ index = opt - 'a';
+ if(index < 0 || index > 25) return -1;
+
+ /* Return number of arguments for this option */
+ return(cmdline_data.opt_args[index].optc);
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+int cmdline_getarg(void* list, int num)
+{
+ int i;
+ CMDLINE_ARGS* p_args = (CMDLINE_ARGS*)list;
+ CMDLINE_ARG* p_arg;
+
+ /* Search the 'num' argument in the list for this option */
+ for(i=0,p_arg=p_args->list; (p_arg!=NULL) && (i<p_args->argc); i++, p_arg=p_arg->p_next)
+ {
+ /* if num matches i, we found it */
+ if(i==num) return(p_arg->index);
+ }
+ /* We did not find the specified argument or the list was empty */
+ return -1;
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+int cmdline_configure(CMDLINE_CFG* p_cfg)
+{
+ /* reset global data */
+ memset(&cmdline_cfg,0,sizeof(cmdline_cfg));
+ memset(&cmdline_data,0,sizeof(cmdline_data));
+
+ /* Copy the user's config structure */
+ cmdline_cfg = *p_cfg;
+ return 0;
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+char* cmdline_error(int err)
+{
+ /* TODO: implement a table of error messages */
+ return(cmdline_errmsg);
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+static void cmdline_print_args(CMDLINE_ARGS* p_arglist, char* argv[])
+{
+ CMDLINE_ARG* p_arg;
+
+ printf(" Number of times option was specified: %d\n", p_arglist->optc);
+ printf(" Number of Arguments: %d\n", p_arglist->argc);
+
+ if(p_arglist->argc > 0)
+ {
+ printf(" Argument List: ");
+
+ for(p_arg=p_arglist->list; p_arg != NULL; p_arg=p_arg->p_next)
+ printf("%s ", argv[p_arg->index]);
+ }
+
+ printf("\n");
+}
+
+/* ***************************************************************
+* Print all found command line options and their arguments
+****************************************************************** */
+void cmdline_print(char* argv[])
+{
+ int i;
+
+ /* Check if the command line was parsed */
+ if(cmdline_data.parsed != CMDLINE_TRUE)
+ {
+ printf("The command line has not been parsed yet.\n");
+ return;
+ }
+
+ /* Print out option arguments */
+ for( i = 0; i < 26; i++ )
+ {
+ /* Check if the option was specified */
+ if(cmdline_data.opt_args[i].optc !=0 )
+ {
+ /* Print out option name and arguments */
+ printf("Option: -%c\n", (char)('a'+i));
+ cmdline_print_args(&(cmdline_data.opt_args[i]), argv);
+ }
+ }
+
+ /* Print out global arguments */
+ printf("Global arguments:\n");
+ cmdline_print_args(&(cmdline_data.glb_args), argv);
+}
+
+/* ***************************************************************
+* Print configuration
+****************************************************************** */
+void cmdline_print_cfg(void)
+{
+
+}
+
+static void cmdline_argadd(CMDLINE_ARGS* p_arglist, CMDLINE_ARG* p_arg)
+{
+ CMDLINE_ARG* p_list;
+ CMDLINE_ARG* p_prev=NULL;
+
+ /* See if we had anything in the list */
+ if(p_arglist->argc == 0)
+ {
+ /* Link the argument in */
+ p_arglist->list = p_arg;
+ }
+ else
+ {
+ /* Find the tail of the list */
+ for(p_list=p_arglist->list; p_list != NULL; p_list=p_list->p_next)
+ p_prev = p_list;
+
+ /* Link the argument in */
+ p_prev->p_next=p_arg;
+ }
+
+ /* Keep track of arg number */
+ p_arglist->argc++;
+}
+
+/* ***************************************************************
+* cmdline_read()
+* Read and parse command line arguments
+****************************************************************** */
+int cmdline_read(int argc, char* argv[])
+{
+ int i, option=0;
+
+ /* Process every command line argument in argv[] array */
+ for( i = 1; i < argc; i++ )
+ {
+ /* Does the argument start with a dash? */
+ if( *argv[i] == '-' )
+ {
+ /* The argument must be two characters: a dash, and a letter */
+ if( strlen(argv[i]) != 2 )
+ {
+ /* ERROR: option syntax (needs to be a dash and one letter) */
+ return(CMDLINE_ERR_ERROR);
+ }
+
+ /* Check validity of the option key ('a' through 'z') */
+ if( ((*(argv[i] + 1)) < 'a') || ((*(argv[i] + 1)) > 'z') )
+ {
+ /* ERROR: option sysntax (invalid option key) */
+ return(CMDLINE_ERR_INVKEY);
+ }
+
+ /* Calculate the option index */
+ option = (*(argv[i] + 1)) - 'a';
+ if((option < 0) || (option > 25)) return(CMDLINE_ERR_INVKEY);
+
+ /* Check to see if the option is allowed */
+ if( cmdline_cfg.opts[option].flags & CMDLINE_OPTFLAG_ALLOW )
+ {
+ /* Option allowed. */
+ cmdline_data.opt_args[option].optc++;
+ continue;
+ }
+ else
+ {
+ /* ERROR: Option is not allowed */
+ return(CMDLINE_ERR_ILLOPT);
+ }
+ }
+ else
+ {
+ /* Read the arguments for the option */
+ CMDLINE_ARG* p_arg;
+
+ /* Allocate space for the argument node */
+ p_arg = (CMDLINE_ARG*)calloc(1,sizeof(CMDLINE_ARG));
+ if( p_arg== NULL )
+ {
+ /* ERROR: Can't allocate memory for the argument index */
+ return(CMDLINE_ERR_NOMEM);
+ }
+
+ /* Initialize the argument */
+ p_arg->index = i;
+ p_arg->p_next = NULL;
+
+ /* Check if we can add to the list of arguments for this option */
+ if( (option < 0) /* Do we have to add to the global list? */
+ || (cmdline_data.opt_args[option].argc == cmdline_cfg.opts[option].max) /* Did we reach MAX arguments? */
+ )
+ {
+ /* This option does not require arguments. Keep the argument in the global list. */
+ cmdline_argadd(&(cmdline_data.glb_args), p_arg);
+ continue;
+ }
+ else
+ {
+ /* See if the current count has reached max for this option */
+ if( cmdline_data.opt_args[option].argc == cmdline_cfg.opts[option].max )
+ {
+ /* ERROR: too many arguments for an option */
+ return(CMDLINE_ERR_MANYARG);
+ }
+ else
+ {
+ /* Link the argument to the arg list of the option */
+ cmdline_argadd(&(cmdline_data.opt_args[option]), p_arg);
+ continue;
+ }
+ }
+ }
+ }
+
+ /* ****** We read the complete command line. See if what we collected matches the configuration ******* */
+
+ /* Check every collected option against its configuration */
+ for( i=0; i < 26; i++ )
+ {
+ /* Check if this option was allowed */
+ if(cmdline_cfg.opts[i].flags & CMDLINE_OPTFLAG_ALLOW)
+ {
+ /* See if it was mandatory */
+ if(cmdline_cfg.opts[i].flags & CMDLINE_OPTFLAG_MANDAT)
+ {
+ /* Check if we really collected this option on the command line. */
+ if(cmdline_data.opt_args[i].optc == 0)
+ {
+ /* ERROR: a missing mandatory option */
+ return(CMDLINE_ERR_OPTMIS);
+ }
+ else
+ {
+ /* Option was there. Check how many args we got for it. */
+ if(cmdline_data.opt_args[i].argc < cmdline_cfg.opts[i].min)
+ {
+ /* ERROR: too few arguments for an option */
+ return(CMDLINE_ERR_FEWARG);
+ }
+ else
+ {
+ /* This mandatory option was proper. */
+ continue;
+ }
+ }
+ }
+ else /* This is non-mandatory option: */
+ {
+ /* Check if the option was specified on the command line */
+ if(cmdline_data.opt_args[i].optc == 0)
+ {
+ /* option wasn't specified, go to the next */
+ continue;
+ }
+ else
+ {
+ /* Option was there. Check how many args we collected for it. */
+ if(cmdline_data.opt_args[i].argc < cmdline_cfg.opts[i].min)
+ {
+ /* ERROR: too few arguments for a non-mandatory option */
+ return(CMDLINE_ERR_FEWARG);
+ }
+ else
+ {
+ /* This non-mandatory option was proper. */
+ continue;
+ }
+ }
+ }
+ }
+ else /* Option was not allowed. */
+ {
+ /* We should not get here as the non-allowed options should have been
+ trapped eariler. */
+ }
+ }
+
+ /* Command line was proper as far as the number of options and their arguments */
+ cmdline_data.parsed = CMDLINE_TRUE;
+ return(CMDLINE_ERR_OK);
+}
diff --git a/tools/firmware-utils/src/mktitanimg.h b/tools/firmware-utils/src/mktitanimg.h
new file mode 100644
index 0000000..9ff30f6
--- /dev/null
+++ b/tools/firmware-utils/src/mktitanimg.h
@@ -0,0 +1,171 @@
+#ifndef __MKTITANIMG_H
+#define __MKTITANIMG_H
+
+#ifndef CFGMGR_CKSUM_H
+#define CFGMGR_CKSUM_H
+
+#define CKSUM_MAGIC_NUMBER 0xC453DE23
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <errno.h>
+
+int cs_is_tagged(FILE*);
+unsigned long cs_read_sum(FILE*);
+int cs_calc_sum(FILE*, unsigned long*, int);
+int cs_set_sum(FILE*, unsigned long, int);
+void cs_get_sum(FILE*, unsigned long*);
+unsigned long cs_calc_buf_sum(char*, int);
+int cs_validate_file(char*);
+
+#endif
+#ifndef ___CMDLINE_H___
+#define ___CMDLINE_H___
+
+/* ********* Library Configuration ********* */
+typedef struct CMDLINE_OPT
+{
+ int min; /* Minimum number of arguments this option takes */
+ int max; /* Maximum number of arguments this option takes */
+ int flags; /* Controlling flags (whether to accept or not, etc) */
+} CMDLINE_OPT;
+
+typedef struct CMDLINE_CFG
+{
+ CMDLINE_OPT opts[26]; /* Options 'a' through 'z' */
+ CMDLINE_OPT global; /* Global option (outside 'a'..'z') */
+} CMDLINE_CFG;
+/* ******************************************** */
+
+#define CMDLINE_OPTFLAG_ALLOW 0x1 /* The option is allowed */
+#define CMDLINE_OPTFLAG_MANDAT 0x2 /* The option is mandatory */
+
+extern void cmdline_print(char* argv[]);
+
+extern int cmdline_configure(CMDLINE_CFG* p_cfg);
+extern int cmdline_read(int argc, char* argv[]);
+
+extern void* cmdline_getarg_list(char opt);
+extern int cmdline_getarg_count(void* list);
+extern int cmdline_getopt_count(char opt);
+extern int cmdline_getarg(void* list, int num);
+
+extern char* cmdline_error(int err);
+#endif
+
+
+#ifndef _NSPIMGHDR_H_
+#define _NSPIMGHDR_H_
+
+/* This file describes the header format for the single image. The image is broken
+ up into several pieces. The image contains this header plus 1 or more sections.
+ Each section contains a binary block that could be a kernel, filesystem, etc. The
+ only garentee for this is that the very first section MUST be executable. Meaning
+ that the bootloader will be able to take the address of the header start, add the
+ header size, and execute that binary block. The header has its own checksum. It
+ starts hdr_size-4 bytes from the start of the header.
+ */
+
+struct nsp_img_hdr_head
+{
+ unsigned int magic; /* Magic number to identify this image header */
+ unsigned int boot_offset; /* Offset from start of header to kernel code. */
+ unsigned int flags; /* Image flags. */
+ unsigned int hdr_version; /* Version of this header. */
+ unsigned int hdr_size; /* The complete size of all portions of the header */
+ unsigned int prod_id; /* This product id */
+ unsigned int rel_id; /* Which release this is */
+ unsigned int version; /* name-MMM.nnn.ooo-rxx => 0xMMnnooxx. See comment
+ below */
+ unsigned int image_size; /* Image size (including header) */
+ unsigned int info_offset; /* Offset from start of header to info block */
+ unsigned int sect_info_offset; /* Offset from start of header to section desc */
+ unsigned int chksum_offset; /* Offset from start of header to chksum block */
+// unsigned int pad1;
+};
+
+/* The patch id is a machine readable value that takes the normal patch level, and encodes
+ the correct numbers inside of it. The format of the patches are name-MM.NN.oo-rxx.bin.
+ Convert MM, NN, oo, and xx into hex, and encode them as 0xMMNNooxx. Thus:
+ att-1.2.18-r14.bin => 0x0102120e */
+
+/* The following are the flag bits for the above flags variable */
+/* List of NSP status flags: */
+#define NSP_IMG_FLAG_FAILBACK_MASK 0xF8000000
+
+/* NSP Image status flag: Flag indicates individual sections image */
+#define NSP_IMG_FLAG_INDIVIDUAL 0x00000001
+
+/* NSP Image status flag 1: Image contains a bootable image when this bit is 0 */
+#define NSP_IMG_FLAG_FAILBACK_1 0x08000000
+
+/* NSP Image status flag 2: Image contains a non-bootable image when this bit is 0 */
+#define NSP_IMG_FLAG_FAILBACK_2 0x10000000
+
+/* NSP Image status flag 3: PSPBoot has tried the image when this bit is 0 */
+#define NSP_IMG_FLAG_FAILBACK_3 0x20000000
+
+/* NSP Image status flag 4: Image is now secondary image when this bit is 0 */
+#define NSP_IMG_FLAG_FAILBACK_4 0x40000000
+
+/* NSP Image status flag 5: Image contains a valid image when this bit is 0 */
+#define NSP_IMG_FLAG_FAILBACK_5 0x80000000
+
+/* NSP Single image magic number */
+#define NSP_IMG_MAGIC_NUMBER 0x4D544443
+
+
+struct nsp_img_hdr_info
+{
+ char release_name[64]; /* Name of release */
+ char image_filename[64]; /* name-mm.nn.oo-rxx.bin format */
+};
+
+struct nsp_img_hdr_section_info
+{
+ unsigned int num_sects; /* Number of section (and section desc blocks) in this
+ image */
+ unsigned int sect_size; /* Size of a SINGLE section_desc block */
+ unsigned int sections_offset; /* Offset to from start of header to the start of
+ the section blocks */
+};
+
+/* There will be one of more of the following stuctures in the image header. Each
+ section will have one of these blocks. */
+struct nsp_img_hdr_sections
+{
+ unsigned int offset; /* Offset of section from start of NSP_IMG_HDR_HEAD */
+ unsigned int total_size; /* Size of section (including pad size.) */
+ unsigned int raw_size; /* Size of section only */
+ unsigned int flags; /* Section flags */
+ unsigned int chksum; /* Section checksum */
+ unsigned int type; /* Section type. What kind of info does this section
+ describe */
+ char name[16]; /* Reference name for this section. */
+};
+#define NSP_IMG_SECTION_TYPE_KERNEL (0x01)
+#define NSP_IMG_SECTION_TYPE_FILESYSTEM_ROOT (0x02)
+#define NSP_IMG_SECTION_TYPE_FILESYSTEM (0x03)
+
+struct nsp_img_hdr
+{
+ struct nsp_img_hdr_head head; /* Head portion */
+ struct nsp_img_hdr_info info; /* Info */
+ struct nsp_img_hdr_section_info sect_info; /* Section block */
+ struct nsp_img_hdr_sections sections; /* 1 or more section_description blocks. More
+ section_desc blocks will be appended here
+ for each additional section needed */
+};
+
+struct nsp_img_hdr_chksum
+{
+ unsigned int hdr_chksum; /* The checksum for the complete header. Excepting the
+ checksum block */
+};
+
+struct nsp_img_hdr_sections *nsp_img_hdr_get_section_ptr_by_name(struct nsp_img_hdr *hdr, char *name);
+unsigned int nsp_img_hdr_get_section_offset_by_name(struct nsp_img_hdr *hdr, char *name);
+unsigned int nsp_img_hdr_get_section_size_by_name(struct nsp_img_hdr *hdr, char *name);
+
+#endif
+#endif /* __MKTITANIMG_H */
diff --git a/tools/firmware-utils/src/mktplinkfw.c b/tools/firmware-utils/src/mktplinkfw.c
new file mode 100644
index 0000000..4922afb
--- /dev/null
+++ b/tools/firmware-utils/src/mktplinkfw.c
@@ -0,0 +1,1222 @@
+/*
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This tool was based on:
+ * TP-Link WR941 V2 firmware checksum fixing tool.
+ * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "md5.h"
+
+#define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
+
+#define HEADER_VERSION_V1 0x01000000
+#define HEADER_VERSION_V2 0x02000000
+#define HWID_ANTMINER_S1 0x04440101
+#define HWID_ANTMINER_S3 0x04440301
+#define HWID_GL_INET_V1 0x08000001
+#define HWID_GS_OOLITE_V1 0x3C000101
+#define HWID_ONION_OMEGA 0x04700001
+#define HWID_TL_MR10U_V1 0x00100101
+#define HWID_TL_MR13U_V1 0x00130101
+#define HWID_TL_MR3020_V1 0x30200001
+#define HWID_TL_MR3220_V1 0x32200001
+#define HWID_TL_MR3220_V2 0x32200002
+#define HWID_TL_MR3420_V1 0x34200001
+#define HWID_TL_MR3420_V2 0x34200002
+#define HWID_TL_WA701N_V1 0x07010001
+#define HWID_TL_WA701N_V2 0x07010002
+#define HWID_TL_WA7210N_V2 0x72100002
+#define HWID_TL_WA7510N_V1 0x75100001
+#define HWID_TL_WA801ND_V1 0x08010001
+#define HWID_TL_WA830RE_V1 0x08300010
+#define HWID_TL_WA830RE_V2 0x08300002
+#define HWID_TL_WA801ND_V2 0x08010002
+#define HWID_TL_WA901ND_V1 0x09010001
+#define HWID_TL_WA901ND_V2 0x09010002
+#define HWID_TL_WDR4300_V1_IL 0x43008001
+#define HWID_TL_WDR4900_V1 0x49000001
+#define HWID_TL_WR703N_V1 0x07030101
+#define HWID_TL_WR720N_V3 0x07200103
+#define HWID_TL_WR720N_V4 0x07200104
+#define HWID_TL_WR741ND_V1 0x07410001
+#define HWID_TL_WR741ND_V4 0x07410004
+#define HWID_TL_WR740N_V1 0x07400001
+#define HWID_TL_WR740N_V3 0x07400003
+#define HWID_TL_WR743ND_V1 0x07430001
+#define HWID_TL_WR743ND_V2 0x07430002
+#define HWID_TL_WR841N_V1_5 0x08410002
+#define HWID_TL_WR841ND_V3 0x08410003
+#define HWID_TL_WR841ND_V5 0x08410005
+#define HWID_TL_WR841ND_V7 0x08410007
+#define HWID_TL_WR941ND_V2 0x09410002
+#define HWID_TL_WR941ND_V4 0x09410004
+#define HWID_TL_WR1043ND_V1 0x10430001
+#define HWID_TL_WR1043ND_V2 0x10430002
+#define HWID_TL_WR1041N_V2 0x10410002
+#define HWID_TL_WR2543N_V1 0x25430001
+
+#define MD5SUM_LEN 16
+
+struct file_info {
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+};
+
+struct fw_header {
+ uint32_t version; /* header version */
+ char vendor_name[24];
+ char fw_version[36];
+ uint32_t hw_id; /* hardware id */
+ uint32_t hw_rev; /* hardware revision */
+ uint32_t unk1;
+ uint8_t md5sum1[MD5SUM_LEN];
+ uint32_t unk2;
+ uint8_t md5sum2[MD5SUM_LEN];
+ uint32_t unk3;
+ uint32_t kernel_la; /* kernel load address */
+ uint32_t kernel_ep; /* kernel entry point */
+ uint32_t fw_length; /* total length of the firmware */
+ uint32_t kernel_ofs; /* kernel data offset */
+ uint32_t kernel_len; /* kernel data length */
+ uint32_t rootfs_ofs; /* rootfs data offset */
+ uint32_t rootfs_len; /* rootfs data length */
+ uint32_t boot_ofs; /* bootloader data offset */
+ uint32_t boot_len; /* bootloader data length */
+ uint16_t ver_hi;
+ uint16_t ver_mid;
+ uint16_t ver_lo;
+ uint8_t pad[354];
+} __attribute__ ((packed));
+
+struct flash_layout {
+ char *id;
+ uint32_t fw_max_len;
+ uint32_t kernel_la;
+ uint32_t kernel_ep;
+ uint32_t rootfs_ofs;
+};
+
+struct board_info {
+ char *id;
+ uint32_t hw_id;
+ uint32_t hw_rev;
+ char *layout_id;
+};
+
+/*
+ * Globals
+ */
+static char *ofname;
+static char *progname;
+static char *vendor = "TP-LINK Technologies";
+static char *version = "ver. 1.0";
+static char *fw_ver = "0.0.0";
+static uint32_t hdr_ver = HEADER_VERSION_V1;
+
+static char *board_id;
+static struct board_info *board;
+static char *layout_id;
+static struct flash_layout *layout;
+static char *opt_hw_id;
+static uint32_t hw_id;
+static char *opt_hw_rev;
+static uint32_t hw_rev;
+static uint32_t opt_hdr_ver = 1;
+static int fw_ver_lo;
+static int fw_ver_mid;
+static int fw_ver_hi;
+static struct file_info kernel_info;
+static uint32_t kernel_la = 0;
+static uint32_t kernel_ep = 0;
+static uint32_t kernel_len = 0;
+static struct file_info rootfs_info;
+static uint32_t rootfs_ofs = 0;
+static uint32_t rootfs_align;
+static struct file_info boot_info;
+static int combined;
+static int strip_padding;
+static int ignore_size;
+static int add_jffs2_eof;
+static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
+static uint32_t fw_max_len;
+static uint32_t reserved_space;
+
+static struct file_info inspect_info;
+static int extract = 0;
+
+char md5salt_normal[MD5SUM_LEN] = {
+ 0xdc, 0xd7, 0x3a, 0xa5, 0xc3, 0x95, 0x98, 0xfb,
+ 0xdd, 0xf9, 0xe7, 0xf4, 0x0e, 0xae, 0x47, 0x38,
+};
+
+char md5salt_boot[MD5SUM_LEN] = {
+ 0x8c, 0xef, 0x33, 0x5b, 0xd5, 0xc5, 0xce, 0xfa,
+ 0xa7, 0x9c, 0x28, 0xda, 0xb2, 0xe9, 0x0f, 0x42,
+};
+
+static struct flash_layout layouts[] = {
+ {
+ .id = "4M",
+ .fw_max_len = 0x3c0000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x140000,
+ }, {
+ .id = "4Mlzma",
+ .fw_max_len = 0x3c0000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x100000,
+ }, {
+ .id = "8M",
+ .fw_max_len = 0x7c0000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x140000,
+ }, {
+ .id = "8Mlzma",
+ .fw_max_len = 0x7c0000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x100000,
+ }, {
+ .id = "16M",
+ .fw_max_len = 0xf80000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x140000,
+ }, {
+ .id = "16Mlzma",
+ .fw_max_len = 0xf80000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x100000,
+ }, {
+ .id = "16Mppc",
+ .fw_max_len = 0xf80000,
+ .kernel_la = 0x00000000,
+ .kernel_ep = 0xc0000000,
+ .rootfs_ofs = 0x2a0000,
+ }, {
+ /* terminating entry */
+ }
+};
+
+static struct board_info boards[] = {
+ {
+ .id = "TL-MR10Uv1",
+ .hw_id = HWID_TL_MR10U_V1,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-MR13Uv1",
+ .hw_id = HWID_TL_MR13U_V1,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-MR3020v1",
+ .hw_id = HWID_TL_MR3020_V1,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-MR3220v1",
+ .hw_id = HWID_TL_MR3220_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-MR3220v2",
+ .hw_id = HWID_TL_MR3220_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-MR3420v1",
+ .hw_id = HWID_TL_MR3420_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-MR3420v2",
+ .hw_id = HWID_TL_MR3420_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WA701Nv1",
+ .hw_id = HWID_TL_WA701N_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WA701Nv2",
+ .hw_id = HWID_TL_WA701N_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WA7210N",
+ .hw_id = HWID_TL_WA7210N_V2,
+ .hw_rev = 2,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WA7510N",
+ .hw_id = HWID_TL_WA7510N_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WA801NDv1",
+ .hw_id = HWID_TL_WA801ND_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WA830REv1",
+ .hw_id = HWID_TL_WA830RE_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WA830REv2",
+ .hw_id = HWID_TL_WA830RE_V2,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WA801NDv2",
+ .hw_id = HWID_TL_WA801ND_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WA901NDv1",
+ .hw_id = HWID_TL_WA901ND_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WA901NDv2",
+ .hw_id = HWID_TL_WA901ND_V2,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WDR4300v1",
+ .hw_id = HWID_TL_WDR4300_V1_IL,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ .id = "TL-WDR4900v1",
+ .hw_id = HWID_TL_WDR4900_V1,
+ .hw_rev = 1,
+ .layout_id = "16Mppc",
+ }, {
+ .id = "TL-WR741NDv1",
+ .hw_id = HWID_TL_WR741ND_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR741NDv4",
+ .hw_id = HWID_TL_WR741ND_V4,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WR740Nv1",
+ .hw_id = HWID_TL_WR740N_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR740Nv3",
+ .hw_id = HWID_TL_WR740N_V3,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR743NDv1",
+ .hw_id = HWID_TL_WR743ND_V1,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR743NDv2",
+ .hw_id = HWID_TL_WR743ND_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WR841Nv1.5",
+ .hw_id = HWID_TL_WR841N_V1_5,
+ .hw_rev = 2,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR841NDv3",
+ .hw_id = HWID_TL_WR841ND_V3,
+ .hw_rev = 3,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR841NDv5",
+ .hw_id = HWID_TL_WR841ND_V5,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR841NDv7",
+ .hw_id = HWID_TL_WR841ND_V7,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR941NDv2",
+ .hw_id = HWID_TL_WR941ND_V2,
+ .hw_rev = 2,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR941NDv4",
+ .hw_id = HWID_TL_WR941ND_V4,
+ .hw_rev = 1,
+ .layout_id = "4M",
+ }, {
+ .id = "TL-WR1041Nv2",
+ .hw_id = HWID_TL_WR1041N_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WR1043NDv1",
+ .hw_id = HWID_TL_WR1043ND_V1,
+ .hw_rev = 1,
+ .layout_id = "8M",
+ }, {
+ .id = "TL-WR1043NDv2",
+ .hw_id = HWID_TL_WR1043ND_V2,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ .id = "TL-WR2543Nv1",
+ .hw_id = HWID_TL_WR2543N_V1,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ .id = "TL-WR703Nv1",
+ .hw_id = HWID_TL_WR703N_V1,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WR720Nv3",
+ .hw_id = HWID_TL_WR720N_V3,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "TL-WR720Nv4",
+ .hw_id = HWID_TL_WR720N_V4,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
+ }, {
+ .id = "GL-INETv1",
+ .hw_id = HWID_GL_INET_V1,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ .id = "GS-OOLITEv1",
+ .hw_id = HWID_GS_OOLITE_V1,
+ .hw_rev = 1,
+ .layout_id = "16Mlzma",
+ }, {
+ .id = "ONION-OMEGA",
+ .hw_id = HWID_ONION_OMEGA,
+ .hw_rev = 1,
+ .layout_id = "16Mlzma",
+ }, {
+ .id = "ANTMINER-S1",
+ .hw_id = HWID_ANTMINER_S1,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ .id = "ANTMINER-S3",
+ .hw_id = HWID_ANTMINER_S3,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ /* terminating entry */
+ }
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static struct board_info *find_board(char *id)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->id != NULL; board++){
+ if (strcasecmp(id, board->id) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+static struct board_info *find_board_by_hwid(uint32_t hw_id)
+{
+ struct board_info *board;
+
+ for (board = boards; board->id != NULL; board++) {
+ if (hw_id == board->hw_id)
+ return board;
+ };
+
+ return NULL;
+}
+
+static struct flash_layout *find_layout(char *id)
+{
+ struct flash_layout *ret;
+ struct flash_layout *l;
+
+ ret = NULL;
+ for (l = layouts; l->id != NULL; l++){
+ if (strcasecmp(id, l->id) == 0) {
+ ret = l;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>\n"
+" -c use combined kernel image\n"
+" -E <ep> overwrite kernel entry point with <ep> (hexval prefixed with 0x)\n"
+" -L <la> overwrite kernel load address with <la> (hexval prefixed with 0x)\n"
+" -H <hwid> use hardware id specified with <hwid>\n"
+" -W <hwrev> use hardware revision specified with <hwrev>\n"
+" -F <id> use flash layout specified with <id>\n"
+" -k <file> read kernel image from the file <file>\n"
+" -r <file> read rootfs image from the file <file>\n"
+" -a <align> align the rootfs start on an <align> bytes boundary\n"
+" -R <offset> overwrite rootfs offset with <offset> (hexval prefixed with 0x)\n"
+" -o <file> write output to the file <file>\n"
+" -s strip padding from the end of the image\n"
+" -S ignore firmware size limit (only for combined images)\n"
+" -j add jffs2 end-of-filesystem markers\n"
+" -N <vendor> set image vendor to <vendor>\n"
+" -V <version> set image version to <version>\n"
+" -v <version> set firmware version to <version>\n"
+" -m <version> set header version to <version>\n"
+" -i <file> inspect given firmware file <file>\n"
+" -x extract kernel and rootfs while inspecting (requires -i)\n"
+" -X <size> reserve <size> bytes in the firmware image (hexval prefixed with 0x)\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static int get_md5(char *data, int size, char *md5)
+{
+ MD5_CTX ctx;
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, data, size);
+ MD5_Final(md5, &ctx);
+}
+
+static int get_file_stat(struct file_info *fdata)
+{
+ struct stat st;
+ int res;
+
+ if (fdata->file_name == NULL)
+ return 0;
+
+ res = stat(fdata->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", fdata->file_name);
+ return res;
+ }
+
+ fdata->file_size = st.st_size;
+ return 0;
+}
+
+static int read_to_buf(struct file_info *fdata, char *buf)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(fdata->file_name, "r");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", fdata->file_name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, fdata->file_size, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", fdata->file_name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+ out_close:
+ fclose(f);
+ out:
+ return ret;
+}
+
+static int check_options(void)
+{
+ int ret;
+ int exceed_bytes;
+
+ if (inspect_info.file_name) {
+ ret = get_file_stat(&inspect_info);
+ if (ret)
+ return ret;
+
+ return 0;
+ } else if (extract) {
+ ERR("no firmware for inspection specified");
+ return -1;
+ }
+
+ if (board_id == NULL && opt_hw_id == NULL) {
+ ERR("either board or hardware id must be specified");
+ return -1;
+ }
+
+ if (board_id) {
+ board = find_board(board_id);
+ if (board == NULL) {
+ ERR("unknown/unsupported board id \"%s\"", board_id);
+ return -1;
+ }
+ if (layout_id == NULL)
+ layout_id = board->layout_id;
+
+ hw_id = board->hw_id;
+ hw_rev = board->hw_rev;
+ } else {
+ if (layout_id == NULL) {
+ ERR("flash layout is not specified");
+ return -1;
+ }
+ hw_id = strtoul(opt_hw_id, NULL, 0);
+
+ if (opt_hw_rev)
+ hw_rev = strtoul(opt_hw_rev, NULL, 0);
+ else
+ hw_rev = 1;
+ }
+
+ layout = find_layout(layout_id);
+ if (layout == NULL) {
+ ERR("unknown flash layout \"%s\"", layout_id);
+ return -1;
+ }
+
+ if (!kernel_la)
+ kernel_la = layout->kernel_la;
+ if (!kernel_ep)
+ kernel_ep = layout->kernel_ep;
+ if (!rootfs_ofs)
+ rootfs_ofs = layout->rootfs_ofs;
+
+ if (reserved_space > layout->fw_max_len) {
+ ERR("reserved space is not valid");
+ return -1;
+ }
+
+ fw_max_len = layout->fw_max_len - reserved_space;
+
+ if (kernel_info.file_name == NULL) {
+ ERR("no kernel image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&kernel_info);
+ if (ret)
+ return ret;
+
+ kernel_len = kernel_info.file_size;
+
+ if (combined) {
+ exceed_bytes = kernel_info.file_size - (fw_max_len - sizeof(struct fw_header));
+ if (exceed_bytes > 0) {
+ if (!ignore_size) {
+ ERR("kernel image is too big by %i bytes", exceed_bytes);
+ return -1;
+ }
+ layout->fw_max_len = sizeof(struct fw_header) +
+ kernel_info.file_size +
+ reserved_space;
+ }
+ } else {
+ if (rootfs_info.file_name == NULL) {
+ ERR("no rootfs image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&rootfs_info);
+ if (ret)
+ return ret;
+
+ if (rootfs_align) {
+ kernel_len += sizeof(struct fw_header);
+ kernel_len = ALIGN(kernel_len, rootfs_align);
+ kernel_len -= sizeof(struct fw_header);
+
+ DBG("kernel length aligned to %u", kernel_len);
+
+ exceed_bytes = kernel_len + rootfs_info.file_size - (fw_max_len - sizeof(struct fw_header));
+ if (exceed_bytes > 0) {
+ ERR("images are too big by %i bytes", exceed_bytes);
+ return -1;
+ }
+ } else {
+ exceed_bytes = kernel_info.file_size - (rootfs_ofs - sizeof(struct fw_header));
+ if (exceed_bytes > 0) {
+ ERR("kernel image is too big");
+ return -1;
+ }
+
+ exceed_bytes = rootfs_info.file_size - (fw_max_len - rootfs_ofs);
+ if (exceed_bytes > 0) {
+ ERR("rootfs image is too big");
+ return -1;
+ }
+ }
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ return -1;
+ }
+
+ ret = sscanf(fw_ver, "%d.%d.%d", &fw_ver_hi, &fw_ver_mid, &fw_ver_lo);
+ if (ret != 3) {
+ ERR("invalid firmware version '%s'", fw_ver);
+ return -1;
+ }
+
+ if (opt_hdr_ver == 1) {
+ hdr_ver = HEADER_VERSION_V1;
+ } else if (opt_hdr_ver == 2) {
+ hdr_ver = HEADER_VERSION_V2;
+ } else {
+ ERR("invalid header version '%u'", opt_hdr_ver);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void fill_header(char *buf, int len)
+{
+ struct fw_header *hdr = (struct fw_header *)buf;
+
+ memset(hdr, 0, sizeof(struct fw_header));
+
+ hdr->version = htonl(hdr_ver);
+ strncpy(hdr->vendor_name, vendor, sizeof(hdr->vendor_name));
+ strncpy(hdr->fw_version, version, sizeof(hdr->fw_version));
+ hdr->hw_id = htonl(hw_id);
+ hdr->hw_rev = htonl(hw_rev);
+
+ if (boot_info.file_size == 0)
+ memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1));
+ else
+ memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1));
+
+ hdr->kernel_la = htonl(kernel_la);
+ hdr->kernel_ep = htonl(kernel_ep);
+ hdr->fw_length = htonl(layout->fw_max_len);
+ hdr->kernel_ofs = htonl(sizeof(struct fw_header));
+ hdr->kernel_len = htonl(kernel_len);
+ if (!combined) {
+ hdr->rootfs_ofs = htonl(rootfs_ofs);
+ hdr->rootfs_len = htonl(rootfs_info.file_size);
+ }
+
+ hdr->ver_hi = htons(fw_ver_hi);
+ hdr->ver_mid = htons(fw_ver_mid);
+ hdr->ver_lo = htons(fw_ver_lo);
+
+ get_md5(buf, len, hdr->md5sum1);
+}
+
+static int pad_jffs2(char *buf, int currlen)
+{
+ int len;
+ uint32_t pad_mask;
+
+ len = currlen;
+ pad_mask = (64 * 1024);
+ while ((len < layout->fw_max_len) && (pad_mask != 0)) {
+ uint32_t mask;
+ int i;
+
+ for (i = 10; i < 32; i++) {
+ mask = 1 << i;
+ if (pad_mask & mask)
+ break;
+ }
+
+ len = ALIGN(len, mask);
+
+ for (i = 10; i < 32; i++) {
+ mask = 1 << i;
+ if ((len & (mask - 1)) == 0)
+ pad_mask &= ~mask;
+ }
+
+ for (i = 0; i < sizeof(jffs2_eof_mark); i++)
+ buf[len + i] = jffs2_eof_mark[i];
+
+ len += sizeof(jffs2_eof_mark);
+ }
+
+ return len;
+}
+
+static int write_fw(char *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "w");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ DBG("firmware file \"%s\" completed", ofname);
+
+ ret = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+ out:
+ return ret;
+}
+
+static int build_fw(void)
+{
+ int buflen;
+ char *buf;
+ char *p;
+ int ret = EXIT_FAILURE;
+ int writelen = 0;
+
+ buflen = layout->fw_max_len;
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ memset(buf, 0xff, buflen);
+ p = buf + sizeof(struct fw_header);
+ ret = read_to_buf(&kernel_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ writelen = sizeof(struct fw_header) + kernel_len;
+
+ if (!combined) {
+ if (rootfs_align)
+ p = buf + writelen;
+ else
+ p = buf + rootfs_ofs;
+
+ ret = read_to_buf(&rootfs_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ if (rootfs_align)
+ writelen += rootfs_info.file_size;
+ else
+ writelen = rootfs_ofs + rootfs_info.file_size;
+
+ if (add_jffs2_eof)
+ writelen = pad_jffs2(buf, writelen);
+ }
+
+ if (!strip_padding)
+ writelen = buflen;
+
+ fill_header(buf, writelen);
+ ret = write_fw(buf, writelen);
+ if (ret)
+ goto out_free_buf;
+
+ ret = EXIT_SUCCESS;
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+/* Helper functions to inspect_fw() representing different output formats */
+static inline void inspect_fw_pstr(char *label, char *str)
+{
+ printf("%-23s: %s\n", label, str);
+}
+
+static inline void inspect_fw_phex(char *label, uint32_t val)
+{
+ printf("%-23s: 0x%08x\n", label, val);
+}
+
+static inline void inspect_fw_phexpost(char *label,
+ uint32_t val, char *post)
+{
+ printf("%-23s: 0x%08x (%s)\n", label, val, post);
+}
+
+static inline void inspect_fw_phexdef(char *label,
+ uint32_t val, uint32_t defval)
+{
+ printf("%-23s: 0x%08x ", label, val);
+
+ if (val == defval)
+ printf("(== OpenWrt default)\n");
+ else
+ printf("(OpenWrt default: 0x%08x)\n", defval);
+}
+
+static inline void inspect_fw_phexexp(char *label,
+ uint32_t val, uint32_t expval)
+{
+ printf("%-23s: 0x%08x ", label, val);
+
+ if (val == expval)
+ printf("(ok)\n");
+ else
+ printf("(expected: 0x%08x)\n", expval);
+}
+
+static inline void inspect_fw_phexdec(char *label, uint32_t val)
+{
+ printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
+}
+
+static inline void inspect_fw_phexdecdef(char *label,
+ uint32_t val, uint32_t defval)
+{
+ printf("%-23s: 0x%08x / %8u bytes ", label, val, val);
+
+ if (val == defval)
+ printf("(== OpenWrt default)\n");
+ else
+ printf("(OpenWrt default: 0x%08x)\n", defval);
+}
+
+static inline void inspect_fw_pmd5sum(char *label, uint8_t *val, char *text)
+{
+ int i;
+
+ printf("%-23s:", label);
+ for (i=0; i<MD5SUM_LEN; i++)
+ printf(" %02x", val[i]);
+ printf(" %s\n", text);
+}
+
+static int inspect_fw(void)
+{
+ char *buf;
+ struct fw_header *hdr;
+ uint8_t md5sum[MD5SUM_LEN];
+ struct board_info *board;
+ int ret = EXIT_FAILURE;
+
+ buf = malloc(inspect_info.file_size);
+ if (!buf) {
+ ERR("no memory for buffer!\n");
+ goto out;
+ }
+
+ ret = read_to_buf(&inspect_info, buf);
+ if (ret)
+ goto out_free_buf;
+ hdr = (struct fw_header *)buf;
+
+ inspect_fw_pstr("File name", inspect_info.file_name);
+ inspect_fw_phexdec("File size", inspect_info.file_size);
+
+ if ((ntohl(hdr->version) != HEADER_VERSION_V1) &&
+ (ntohl(hdr->version) != HEADER_VERSION_V2)) {
+ ERR("file does not seem to have V1/V2 header!\n");
+ goto out_free_buf;
+ }
+
+ inspect_fw_phexdec("Version 1 Header size", sizeof(struct fw_header));
+
+ if (ntohl(hdr->unk1) != 0)
+ inspect_fw_phexdec("Unknown value 1", hdr->unk1);
+
+ memcpy(md5sum, hdr->md5sum1, sizeof(md5sum));
+ if (ntohl(hdr->boot_len) == 0)
+ memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum));
+ else
+ memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum));
+ get_md5(buf, inspect_info.file_size, hdr->md5sum1);
+
+ if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) {
+ inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)");
+ inspect_fw_pmd5sum(" --> expected", hdr->md5sum1, "");
+ } else {
+ inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)");
+ }
+ if (ntohl(hdr->unk2) != 0)
+ inspect_fw_phexdec("Unknown value 2", hdr->unk2);
+ inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2,
+ "(purpose yet unknown, unchecked here)");
+ if (ntohl(hdr->unk3) != 0)
+ inspect_fw_phexdec("Unknown value 3", hdr->unk3);
+
+ printf("\n");
+
+ inspect_fw_pstr("Vendor name", hdr->vendor_name);
+ inspect_fw_pstr("Firmware version", hdr->fw_version);
+ board = find_board_by_hwid(ntohl(hdr->hw_id));
+ if (board) {
+ layout = find_layout(board->layout_id);
+ inspect_fw_phexpost("Hardware ID",
+ ntohl(hdr->hw_id), board->id);
+ inspect_fw_phexexp("Hardware Revision",
+ ntohl(hdr->hw_rev), board->hw_rev);
+ } else {
+ inspect_fw_phexpost("Hardware ID",
+ ntohl(hdr->hw_id), "unknown");
+ inspect_fw_phex("Hardware Revision",
+ ntohl(hdr->hw_rev));
+ }
+
+ printf("\n");
+
+ inspect_fw_phexdec("Kernel data offset",
+ ntohl(hdr->kernel_ofs));
+ inspect_fw_phexdec("Kernel data length",
+ ntohl(hdr->kernel_len));
+ if (board) {
+ inspect_fw_phexdef("Kernel load address",
+ ntohl(hdr->kernel_la),
+ layout ? layout->kernel_la : 0xffffffff);
+ inspect_fw_phexdef("Kernel entry point",
+ ntohl(hdr->kernel_ep),
+ layout ? layout->kernel_ep : 0xffffffff);
+ inspect_fw_phexdecdef("Rootfs data offset",
+ ntohl(hdr->rootfs_ofs),
+ layout ? layout->rootfs_ofs : 0xffffffff);
+ } else {
+ inspect_fw_phex("Kernel load address",
+ ntohl(hdr->kernel_la));
+ inspect_fw_phex("Kernel entry point",
+ ntohl(hdr->kernel_ep));
+ inspect_fw_phexdec("Rootfs data offset",
+ ntohl(hdr->rootfs_ofs));
+ }
+ inspect_fw_phexdec("Rootfs data length",
+ ntohl(hdr->rootfs_len));
+ inspect_fw_phexdec("Boot loader data offset",
+ ntohl(hdr->boot_ofs));
+ inspect_fw_phexdec("Boot loader data length",
+ ntohl(hdr->boot_len));
+ inspect_fw_phexdec("Total firmware length",
+ ntohl(hdr->fw_length));
+
+ if (extract) {
+ FILE *fp;
+ char *filename;
+
+ printf("\n");
+
+ filename = malloc(strlen(inspect_info.file_name) + 8);
+ sprintf(filename, "%s-kernel", inspect_info.file_name);
+ printf("Extracting kernel to \"%s\"...\n", filename);
+ fp = fopen(filename, "w");
+ if (fp) {
+ if (!fwrite(buf + ntohl(hdr->kernel_ofs),
+ ntohl(hdr->kernel_len), 1, fp)) {
+ ERR("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERR("error in fopen(): %s", strerror(errno));
+ }
+ free(filename);
+
+ filename = malloc(strlen(inspect_info.file_name) + 8);
+ sprintf(filename, "%s-rootfs", inspect_info.file_name);
+ printf("Extracting rootfs to \"%s\"...\n", filename);
+ fp = fopen(filename, "w");
+ if (fp) {
+ if (!fwrite(buf + ntohl(hdr->rootfs_ofs),
+ ntohl(hdr->rootfs_len), 1, fp)) {
+ ERR("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERR("error in fopen(): %s", strerror(errno));
+ }
+ free(filename);
+ }
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ int err;
+
+ FILE *outfile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "a:B:H:E:F:L:m:V:N:W:ci:k:r:R:o:xX:hsSjv:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'a':
+ sscanf(optarg, "0x%x", &rootfs_align);
+ break;
+ case 'B':
+ board_id = optarg;
+ break;
+ case 'H':
+ opt_hw_id = optarg;
+ break;
+ case 'E':
+ sscanf(optarg, "0x%x", &kernel_ep);
+ break;
+ case 'F':
+ layout_id = optarg;
+ break;
+ case 'W':
+ opt_hw_rev = optarg;
+ break;
+ case 'L':
+ sscanf(optarg, "0x%x", &kernel_la);
+ break;
+ case 'm':
+ sscanf(optarg, "%u", &opt_hdr_ver);
+ break;
+ case 'V':
+ version = optarg;
+ break;
+ case 'v':
+ fw_ver = optarg;
+ break;
+ case 'N':
+ vendor = optarg;
+ break;
+ case 'c':
+ combined++;
+ break;
+ case 'k':
+ kernel_info.file_name = optarg;
+ break;
+ case 'r':
+ rootfs_info.file_name = optarg;
+ break;
+ case 'R':
+ sscanf(optarg, "0x%x", &rootfs_ofs);
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 's':
+ strip_padding = 1;
+ break;
+ case 'S':
+ ignore_size = 1;
+ break;
+ case 'i':
+ inspect_info.file_name = optarg;
+ break;
+ case 'j':
+ add_jffs2_eof = 1;
+ break;
+ case 'x':
+ extract = 1;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ case 'X':
+ sscanf(optarg, "0x%x", &reserved_space);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret)
+ goto out;
+
+ if (!inspect_info.file_name)
+ ret = build_fw();
+ else
+ ret = inspect_fw();
+
+ out:
+ return ret;
+}
+
diff --git a/tools/firmware-utils/src/mktplinkfw2.c b/tools/firmware-utils/src/mktplinkfw2.c
new file mode 100644
index 0000000..9277529
--- /dev/null
+++ b/tools/firmware-utils/src/mktplinkfw2.c
@@ -0,0 +1,982 @@
+/*
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This tool was based on:
+ * TP-Link WR941 V2 firmware checksum fixing tool.
+ * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <endian.h>
+#include <sys/stat.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "md5.h"
+
+#define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
+
+#define MD5SUM_LEN 16
+
+struct file_info {
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+};
+
+struct fw_header {
+ uint32_t version; /* 0x00: header version */
+ char fw_version[48]; /* 0x04: fw version string */
+ uint32_t hw_id; /* 0x34: hardware id */
+ uint32_t hw_rev; /* 0x38: FIXME: hardware revision? */
+ uint32_t unk1; /* 0x3c: 0x00000000 */
+ uint8_t md5sum1[MD5SUM_LEN]; /* 0x40 */
+ uint32_t unk2; /* 0x50: 0x00000000 */
+ uint8_t md5sum2[MD5SUM_LEN]; /* 0x54 */
+ uint32_t unk3; /* 0x64: 0xffffffff */
+
+ uint32_t kernel_la; /* 0x68: kernel load address */
+ uint32_t kernel_ep; /* 0x6c: kernel entry point */
+ uint32_t fw_length; /* 0x70: total length of the image */
+ uint32_t kernel_ofs; /* 0x74: kernel data offset */
+ uint32_t kernel_len; /* 0x78: kernel data length */
+ uint32_t rootfs_ofs; /* 0x7c: rootfs data offset */
+ uint32_t rootfs_len; /* 0x80: rootfs data length */
+ uint32_t boot_ofs; /* 0x84: FIXME: seems to be unused */
+ uint32_t boot_len; /* 0x88: FIXME: seems to be unused */
+ uint16_t unk4; /* 0x8c: 0x55aa */
+ uint8_t sver_hi; /* 0x8e */
+ uint8_t sver_lo; /* 0x8f */
+ uint8_t unk5; /* 0x90: magic: 0xa5 */
+ uint8_t ver_hi; /* 0x91 */
+ uint8_t ver_mid; /* 0x92 */
+ uint8_t ver_lo; /* 0x93 */
+ uint8_t pad[364];
+} __attribute__ ((packed));
+
+struct flash_layout {
+ char *id;
+ uint32_t fw_max_len;
+ uint32_t kernel_la;
+ uint32_t kernel_ep;
+ uint32_t rootfs_ofs;
+};
+
+struct board_info {
+ char *id;
+ uint32_t hw_id;
+ uint32_t hw_rev;
+ char *layout_id;
+ uint32_t hdr_ver;
+ bool endian_swap;
+};
+
+/*
+ * Globals
+ */
+static char *ofname;
+static char *progname;
+static char *vendor = "TP-LINK Technologies";
+static char *version = "ver. 1.0";
+static char *fw_ver = "0.0.0";
+static char *sver = "1.0";
+static uint32_t hdr_ver = 2;
+
+static char *board_id;
+static struct board_info *board;
+static char *layout_id;
+static struct flash_layout *layout;
+static char *opt_hw_id;
+static uint32_t hw_id;
+static char *opt_hw_rev;
+static uint32_t hw_rev;
+static int fw_ver_lo;
+static int fw_ver_mid;
+static int fw_ver_hi;
+static int sver_lo;
+static int sver_hi;
+static struct file_info kernel_info;
+static uint32_t kernel_la = 0;
+static uint32_t kernel_ep = 0;
+static uint32_t kernel_len = 0;
+static struct file_info rootfs_info;
+static uint32_t rootfs_ofs = 0;
+static uint32_t rootfs_align;
+static struct file_info boot_info;
+static int combined;
+static int strip_padding;
+static int add_jffs2_eof;
+static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
+
+static struct file_info inspect_info;
+static int extract = 0;
+static bool endian_swap = false;
+
+char md5salt_normal[MD5SUM_LEN] = {
+ 0xdc, 0xd7, 0x3a, 0xa5, 0xc3, 0x95, 0x98, 0xfb,
+ 0xdc, 0xf9, 0xe7, 0xf4, 0x0e, 0xae, 0x47, 0x37,
+};
+
+char md5salt_boot[MD5SUM_LEN] = {
+ 0x8c, 0xef, 0x33, 0x5b, 0xd5, 0xc5, 0xce, 0xfa,
+ 0xa7, 0x9c, 0x28, 0xda, 0xb2, 0xe9, 0x0f, 0x42,
+};
+
+static struct flash_layout layouts[] = {
+ {
+ .id = "8Mltq",
+ .fw_max_len = 0x7a0000,
+ .kernel_la = 0x80002000,
+ .kernel_ep = 0x80002000,
+ .rootfs_ofs = 0x140000,
+ }, {
+ .id = "8Mmtk",
+ .fw_max_len = 0x7a0000,
+ .kernel_la = 0x80000000,
+ .kernel_ep = 0x80000000,
+ .rootfs_ofs = 0x140000,
+ }, {
+ /* terminating entry */
+ }
+};
+
+static struct board_info boards[] = {
+ {
+ .id = "TD-W8970v1",
+ .hw_id = 0x89700001,
+ .hw_rev = 1,
+ .layout_id = "8Mltq",
+ }, {
+ .id = "TD-W8980v1",
+ .hw_id = 0x89800001,
+ .hw_rev = 14,
+ .layout_id = "8Mltq",
+ }, {
+ .id = "ArcherC20i",
+ .hw_id = 0xc2000001,
+ .hw_rev = 58,
+ .layout_id = "8Mmtk",
+ .hdr_ver = 3,
+ .endian_swap = true,
+ }, {
+ /* terminating entry */
+ }
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static struct board_info *find_board(char *id)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->id != NULL; board++){
+ if (strcasecmp(id, board->id) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+static struct board_info *find_board_by_hwid(uint32_t hw_id)
+{
+ struct board_info *board;
+
+ for (board = boards; board->id != NULL; board++) {
+ if (hw_id == board->hw_id)
+ return board;
+ };
+
+ return NULL;
+}
+
+static struct flash_layout *find_layout(char *id)
+{
+ struct flash_layout *ret;
+ struct flash_layout *l;
+
+ ret = NULL;
+ for (l = layouts; l->id != NULL; l++){
+ if (strcasecmp(id, l->id) == 0) {
+ ret = l;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>\n"
+" -c use combined kernel image\n"
+" -E <ep> overwrite kernel entry point with <ep> (hexval prefixed with 0x)\n"
+" -L <la> overwrite kernel load address with <la> (hexval prefixed with 0x)\n"
+" -H <hwid> use hardware id specified with <hwid>\n"
+" -W <hwrev> use hardware revision specified with <hwrev>\n"
+" -F <id> use flash layout specified with <id>\n"
+" -k <file> read kernel image from the file <file>\n"
+" -r <file> read rootfs image from the file <file>\n"
+" -a <align> align the rootfs start on an <align> bytes boundary\n"
+" -R <offset> overwrite rootfs offset with <offset> (hexval prefixed with 0x)\n"
+" -o <file> write output to the file <file>\n"
+" -s strip padding from the end of the image\n"
+" -j add jffs2 end-of-filesystem markers\n"
+" -V <version> set image version to <version>\n"
+" -v <version> set firmware version to <version>\n"
+" -y <version> set secondary version to <version>\n"
+" -i <file> inspect given firmware file <file>\n"
+" -x extract kernel and rootfs while inspecting (requires -i)\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static int get_md5(char *data, int size, char *md5)
+{
+ MD5_CTX ctx;
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, data, size);
+ MD5_Final(md5, &ctx);
+}
+
+static int get_file_stat(struct file_info *fdata)
+{
+ struct stat st;
+ int res;
+
+ if (fdata->file_name == NULL)
+ return 0;
+
+ res = stat(fdata->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", fdata->file_name);
+ return res;
+ }
+
+ fdata->file_size = st.st_size;
+ return 0;
+}
+
+static int read_to_buf(struct file_info *fdata, char *buf)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(fdata->file_name, "r");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", fdata->file_name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, fdata->file_size, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", fdata->file_name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+ out_close:
+ fclose(f);
+ out:
+ return ret;
+}
+
+static int check_options(void)
+{
+ int ret;
+
+ if (inspect_info.file_name) {
+ ret = get_file_stat(&inspect_info);
+ if (ret)
+ return ret;
+
+ return 0;
+ } else if (extract) {
+ ERR("no firmware for inspection specified");
+ return -1;
+ }
+
+ if (board_id == NULL && opt_hw_id == NULL) {
+ ERR("either board or hardware id must be specified");
+ return -1;
+ }
+
+ if (board_id) {
+ board = find_board(board_id);
+ if (board == NULL) {
+ ERR("unknown/unsupported board id \"%s\"", board_id);
+ return -1;
+ }
+ if (layout_id == NULL)
+ layout_id = board->layout_id;
+
+ hw_id = board->hw_id;
+ hw_rev = board->hw_rev;
+ if (board->hdr_ver)
+ hdr_ver = board->hdr_ver;
+ endian_swap = board->endian_swap;
+ } else {
+ if (layout_id == NULL) {
+ ERR("flash layout is not specified");
+ return -1;
+ }
+ hw_id = strtoul(opt_hw_id, NULL, 0);
+
+ if (opt_hw_rev)
+ hw_rev = strtoul(opt_hw_rev, NULL, 0);
+ else
+ hw_rev = 1;
+ }
+
+ layout = find_layout(layout_id);
+ if (layout == NULL) {
+ ERR("unknown flash layout \"%s\"", layout_id);
+ return -1;
+ }
+
+ if (!kernel_la)
+ kernel_la = layout->kernel_la;
+ if (!kernel_ep)
+ kernel_ep = layout->kernel_ep;
+ if (!rootfs_ofs)
+ rootfs_ofs = layout->rootfs_ofs;
+
+ if (kernel_info.file_name == NULL) {
+ ERR("no kernel image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&kernel_info);
+ if (ret)
+ return ret;
+
+ kernel_len = kernel_info.file_size;
+
+ if (combined) {
+ if (kernel_info.file_size >
+ layout->fw_max_len - sizeof(struct fw_header)) {
+ ERR("kernel image is too big");
+ return -1;
+ }
+ } else {
+ if (rootfs_info.file_name == NULL) {
+ ERR("no rootfs image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&rootfs_info);
+ if (ret)
+ return ret;
+
+ if (rootfs_align) {
+ kernel_len += sizeof(struct fw_header);
+ kernel_len = ALIGN(kernel_len, rootfs_align);
+ kernel_len -= sizeof(struct fw_header);
+
+ DBG("kernel length aligned to %u", kernel_len);
+
+ if (kernel_len + rootfs_info.file_size >
+ layout->fw_max_len - sizeof(struct fw_header)) {
+ ERR("images are too big");
+ return -1;
+ }
+ } else {
+ if (kernel_info.file_size >
+ rootfs_ofs - sizeof(struct fw_header)) {
+ ERR("kernel image is too big");
+ return -1;
+ }
+
+ if (rootfs_info.file_size >
+ (layout->fw_max_len - rootfs_ofs)) {
+ ERR("rootfs image is too big");
+ return -1;
+ }
+ }
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ return -1;
+ }
+
+ ret = sscanf(fw_ver, "%d.%d.%d", &fw_ver_hi, &fw_ver_mid, &fw_ver_lo);
+ if (ret != 3) {
+ ERR("invalid firmware version '%s'", fw_ver);
+ return -1;
+ }
+
+ ret = sscanf(sver, "%d.%d", &sver_hi, &sver_lo);
+ if (ret != 2) {
+ ERR("invalid secondary version '%s'", sver);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void fill_header(char *buf, int len)
+{
+ struct fw_header *hdr = (struct fw_header *)buf;
+ unsigned ver_len;
+
+ memset(hdr, '\xff', sizeof(struct fw_header));
+
+ hdr->version = htonl(bswap_32(hdr_ver));
+ ver_len = strlen(version);
+ if (ver_len > (sizeof(hdr->fw_version) - 1))
+ ver_len = sizeof(hdr->fw_version) - 1;
+
+ memcpy(hdr->fw_version, version, ver_len);
+ hdr->fw_version[ver_len] = 0;
+
+ hdr->hw_id = htonl(hw_id);
+ hdr->hw_rev = htonl(hw_rev);
+
+ if (boot_info.file_size == 0) {
+ memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1));
+ hdr->boot_ofs = htonl(0);
+ hdr->boot_len = htonl(0);
+ } else {
+ memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1));
+ hdr->boot_ofs = htonl(rootfs_ofs + rootfs_info.file_size);
+ hdr->boot_len = htonl(rootfs_info.file_size);
+ }
+
+ hdr->kernel_la = htonl(kernel_la);
+ hdr->kernel_ep = htonl(kernel_ep);
+ hdr->fw_length = htonl(layout->fw_max_len);
+ hdr->kernel_ofs = htonl(sizeof(struct fw_header));
+ hdr->kernel_len = htonl(kernel_len);
+ if (!combined) {
+ hdr->rootfs_ofs = htonl(rootfs_ofs);
+ hdr->rootfs_len = htonl(rootfs_info.file_size);
+ }
+
+ hdr->boot_ofs = htonl(0);
+ hdr->boot_len = htonl(boot_info.file_size);
+
+ hdr->unk1 = htonl(0);
+ hdr->unk2 = htonl(0);
+ hdr->unk3 = htonl(0xffffffff);
+ hdr->unk4 = htons(0x55aa);
+ hdr->unk5 = 0xa5;
+
+ hdr->sver_hi = sver_hi;
+ hdr->sver_lo = sver_lo;
+
+ hdr->ver_hi = fw_ver_hi;
+ hdr->ver_mid = fw_ver_mid;
+ hdr->ver_lo = fw_ver_lo;
+
+ if (endian_swap) {
+ hdr->kernel_la = bswap_32(hdr->kernel_la);
+ hdr->kernel_ep = bswap_32(hdr->kernel_ep);
+ }
+
+ get_md5(buf, len, hdr->md5sum1);
+}
+
+static int pad_jffs2(char *buf, int currlen)
+{
+ int len;
+ uint32_t pad_mask;
+
+ len = currlen;
+ pad_mask = (64 * 1024);
+ while ((len < layout->fw_max_len) && (pad_mask != 0)) {
+ uint32_t mask;
+ int i;
+
+ for (i = 10; i < 32; i++) {
+ mask = 1 << i;
+ if (pad_mask & mask)
+ break;
+ }
+
+ len = ALIGN(len, mask);
+
+ for (i = 10; i < 32; i++) {
+ mask = 1 << i;
+ if ((len & (mask - 1)) == 0)
+ pad_mask &= ~mask;
+ }
+
+ for (i = 0; i < sizeof(jffs2_eof_mark); i++)
+ buf[len + i] = jffs2_eof_mark[i];
+
+ len += sizeof(jffs2_eof_mark);
+ }
+
+ return len;
+}
+
+static int write_fw(char *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "w");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ DBG("firmware file \"%s\" completed", ofname);
+
+ ret = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+ out:
+ return ret;
+}
+
+static int build_fw(void)
+{
+ int buflen;
+ char *buf;
+ char *p;
+ int ret = EXIT_FAILURE;
+ int writelen = 0;
+
+ buflen = layout->fw_max_len;
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ memset(buf, 0xff, buflen);
+ p = buf + sizeof(struct fw_header);
+ ret = read_to_buf(&kernel_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ writelen = sizeof(struct fw_header) + kernel_len;
+
+ if (!combined) {
+ if (rootfs_align)
+ p = buf + writelen;
+ else
+ p = buf + rootfs_ofs;
+
+ ret = read_to_buf(&rootfs_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ if (rootfs_align)
+ writelen += rootfs_info.file_size;
+ else
+ writelen = rootfs_ofs + rootfs_info.file_size;
+
+ if (add_jffs2_eof)
+ writelen = pad_jffs2(buf, writelen);
+ }
+
+ if (!strip_padding)
+ writelen = buflen;
+
+ fill_header(buf, writelen);
+ ret = write_fw(buf, writelen);
+ if (ret)
+ goto out_free_buf;
+
+ ret = EXIT_SUCCESS;
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+/* Helper functions to inspect_fw() representing different output formats */
+static inline void inspect_fw_pstr(char *label, char *str)
+{
+ printf("%-23s: %s\n", label, str);
+}
+
+static inline void inspect_fw_phex(char *label, uint32_t val)
+{
+ printf("%-23s: 0x%08x\n", label, val);
+}
+
+static inline void inspect_fw_phexpost(char *label,
+ uint32_t val, char *post)
+{
+ printf("%-23s: 0x%08x (%s)\n", label, val, post);
+}
+
+static inline void inspect_fw_phexdef(char *label,
+ uint32_t val, uint32_t defval)
+{
+ printf("%-23s: 0x%08x ", label, val);
+
+ if (val == defval)
+ printf("(== OpenWrt default)\n");
+ else
+ printf("(OpenWrt default: 0x%08x)\n", defval);
+}
+
+static inline void inspect_fw_phexexp(char *label,
+ uint32_t val, uint32_t expval)
+{
+ printf("%-23s: 0x%08x ", label, val);
+
+ if (val == expval)
+ printf("(ok)\n");
+ else
+ printf("(expected: 0x%08x)\n", expval);
+}
+
+static inline void inspect_fw_phexdec(char *label, uint32_t val)
+{
+ printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
+}
+
+static inline void inspect_fw_phexdecdef(char *label,
+ uint32_t val, uint32_t defval)
+{
+ printf("%-23s: 0x%08x / %8u bytes ", label, val, val);
+
+ if (val == defval)
+ printf("(== OpenWrt default)\n");
+ else
+ printf("(OpenWrt default: 0x%08x)\n", defval);
+}
+
+static inline void inspect_fw_pmd5sum(char *label, uint8_t *val, char *text)
+{
+ int i;
+
+ printf("%-23s:", label);
+ for (i=0; i<MD5SUM_LEN; i++)
+ printf(" %02x", val[i]);
+ printf(" %s\n", text);
+}
+
+static int inspect_fw(void)
+{
+ char *buf;
+ struct fw_header *hdr;
+ uint8_t md5sum[MD5SUM_LEN];
+ struct board_info *board;
+ int ret = EXIT_FAILURE;
+
+ buf = malloc(inspect_info.file_size);
+ if (!buf) {
+ ERR("no memory for buffer!\n");
+ goto out;
+ }
+
+ ret = read_to_buf(&inspect_info, buf);
+ if (ret)
+ goto out_free_buf;
+ hdr = (struct fw_header *)buf;
+
+ inspect_fw_pstr("File name", inspect_info.file_name);
+ inspect_fw_phexdec("File size", inspect_info.file_size);
+
+ switch(bswap_32(ntohl(hdr->version))) {
+ case 2:
+ case 3:
+ break;
+ default:
+ ERR("file does not seem to have V2/V3 header!\n");
+ goto out_free_buf;
+ }
+
+ inspect_fw_phexdec("Version 2 Header size", sizeof(struct fw_header));
+
+ if (ntohl(hdr->unk1) != 0)
+ inspect_fw_phexdec("Unknown value 1", hdr->unk1);
+
+ memcpy(md5sum, hdr->md5sum1, sizeof(md5sum));
+ if (ntohl(hdr->boot_len) == 0)
+ memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum));
+ else
+ memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum));
+ get_md5(buf, inspect_info.file_size, hdr->md5sum1);
+
+ if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) {
+ inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)");
+ inspect_fw_pmd5sum(" --> expected", hdr->md5sum1, "");
+ } else {
+ inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)");
+ }
+ if (ntohl(hdr->unk2) != 0)
+ inspect_fw_phexdec("Unknown value 2", hdr->unk2);
+ inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2,
+ "(purpose yet unknown, unchecked here)");
+
+ if (ntohl(hdr->unk3) != 0xffffffff)
+ inspect_fw_phexdec("Unknown value 3", hdr->unk3);
+
+ if (ntohs(hdr->unk4) != 0x55aa)
+ inspect_fw_phexdec("Unknown value 4", hdr->unk4);
+
+ if (hdr->unk5 != 0xa5)
+ inspect_fw_phexdec("Unknown value 5", hdr->unk5);
+
+ printf("\n");
+
+ inspect_fw_pstr("Firmware version", hdr->fw_version);
+
+ board = find_board_by_hwid(ntohl(hdr->hw_id));
+ if (board) {
+ layout = find_layout(board->layout_id);
+ inspect_fw_phexpost("Hardware ID",
+ ntohl(hdr->hw_id), board->id);
+ inspect_fw_phexexp("Hardware Revision",
+ ntohl(hdr->hw_rev), board->hw_rev);
+ } else {
+ inspect_fw_phexpost("Hardware ID",
+ ntohl(hdr->hw_id), "unknown");
+ inspect_fw_phex("Hardware Revision",
+ ntohl(hdr->hw_rev));
+ }
+
+ printf("%-23s: %d.%d.%d-%d.%d\n", "Software version",
+ hdr->ver_hi, hdr->ver_mid, hdr->ver_lo,
+ hdr->sver_hi, hdr->sver_lo);
+
+ printf("\n");
+
+ inspect_fw_phexdec("Kernel data offset",
+ ntohl(hdr->kernel_ofs));
+ inspect_fw_phexdec("Kernel data length",
+ ntohl(hdr->kernel_len));
+ if (board) {
+ inspect_fw_phexdef("Kernel load address",
+ ntohl(hdr->kernel_la),
+ layout ? layout->kernel_la : 0xffffffff);
+ inspect_fw_phexdef("Kernel entry point",
+ ntohl(hdr->kernel_ep),
+ layout ? layout->kernel_ep : 0xffffffff);
+ inspect_fw_phexdecdef("Rootfs data offset",
+ ntohl(hdr->rootfs_ofs),
+ layout ? layout->rootfs_ofs : 0xffffffff);
+ } else {
+ inspect_fw_phex("Kernel load address",
+ ntohl(hdr->kernel_la));
+ inspect_fw_phex("Kernel entry point",
+ ntohl(hdr->kernel_ep));
+ inspect_fw_phexdec("Rootfs data offset",
+ ntohl(hdr->rootfs_ofs));
+ }
+ inspect_fw_phexdec("Rootfs data length",
+ ntohl(hdr->rootfs_len));
+ inspect_fw_phexdec("Boot loader data offset",
+ ntohl(hdr->boot_ofs));
+ inspect_fw_phexdec("Boot loader data length",
+ ntohl(hdr->boot_len));
+ inspect_fw_phexdec("Total firmware length",
+ ntohl(hdr->fw_length));
+
+ if (extract) {
+ FILE *fp;
+ char *filename;
+
+ printf("\n");
+
+ filename = malloc(strlen(inspect_info.file_name) + 8);
+ sprintf(filename, "%s-kernel", inspect_info.file_name);
+ printf("Extracting kernel to \"%s\"...\n", filename);
+ fp = fopen(filename, "w");
+ if (fp) {
+ if (!fwrite(buf + ntohl(hdr->kernel_ofs),
+ ntohl(hdr->kernel_len), 1, fp)) {
+ ERR("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERR("error in fopen(): %s", strerror(errno));
+ }
+ free(filename);
+
+ filename = malloc(strlen(inspect_info.file_name) + 8);
+ sprintf(filename, "%s-rootfs", inspect_info.file_name);
+ printf("Extracting rootfs to \"%s\"...\n", filename);
+ fp = fopen(filename, "w");
+ if (fp) {
+ if (!fwrite(buf + ntohl(hdr->rootfs_ofs),
+ ntohl(hdr->rootfs_len), 1, fp)) {
+ ERR("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERR("error in fopen(): %s", strerror(errno));
+ }
+ free(filename);
+ }
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ int err;
+
+ FILE *outfile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "a:B:H:E:F:L:V:N:W:ci:k:r:R:o:xhsjv:y:T:e");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'a':
+ sscanf(optarg, "0x%x", &rootfs_align);
+ break;
+ case 'B':
+ board_id = optarg;
+ break;
+ case 'H':
+ opt_hw_id = optarg;
+ break;
+ case 'E':
+ sscanf(optarg, "0x%x", &kernel_ep);
+ break;
+ case 'F':
+ layout_id = optarg;
+ break;
+ case 'W':
+ opt_hw_rev = optarg;
+ break;
+ case 'L':
+ sscanf(optarg, "0x%x", &kernel_la);
+ break;
+ case 'V':
+ version = optarg;
+ break;
+ case 'v':
+ fw_ver = optarg;
+ break;
+ case 'y':
+ sver = optarg;
+ break;
+ case 'N':
+ vendor = optarg;
+ break;
+ case 'c':
+ combined++;
+ break;
+ case 'k':
+ kernel_info.file_name = optarg;
+ break;
+ case 'r':
+ rootfs_info.file_name = optarg;
+ break;
+ case 'R':
+ sscanf(optarg, "0x%x", &rootfs_ofs);
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 's':
+ strip_padding = 1;
+ break;
+ case 'i':
+ inspect_info.file_name = optarg;
+ break;
+ case 'j':
+ add_jffs2_eof = 1;
+ break;
+ case 'x':
+ extract = 1;
+ break;
+ case 'T':
+ hdr_ver = atoi(optarg);
+ break;
+ case 'e':
+ endian_swap = true;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret)
+ goto out;
+
+ if (!inspect_info.file_name)
+ ret = build_fw();
+ else
+ ret = inspect_fw();
+
+ out:
+ return ret;
+}
+
diff --git a/tools/firmware-utils/src/mkwrgimg.c b/tools/firmware-utils/src/mkwrgimg.c
new file mode 100644
index 0000000..3915d14
--- /dev/null
+++ b/tools/firmware-utils/src/mkwrgimg.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "md5.h"
+
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define WRG_MAGIC 0x20040220
+
+struct wrg_header {
+ char signature[32];
+ uint32_t magic1;
+ uint32_t magic2;
+ uint32_t size;
+ uint32_t offset;
+ char devname[32];
+ char digest[16];
+} __attribute__ ((packed));
+
+static char *progname;
+static char *ifname;
+static char *ofname;
+static char *signature;
+static char *dev_name;
+static uint32_t offset;
+static int big_endian;
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -b create image in big endian format\n"
+" -i <file> read input from the file <file>\n"
+" -d <name> set device name to <name>\n"
+" -o <file> write output to the file <file>\n"
+" -O <offset> set offset to <offset>\n"
+" -s <sig> set image signature to <sig>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static void put_u32(void *data, uint32_t val)
+{
+ unsigned char *p = data;
+
+ if (big_endian) {
+ p[0] = (val >> 24) & 0xff;
+ p[1] = (val >> 16) & 0xff;
+ p[2] = (val >> 8) & 0xff;
+ p[3] = val & 0xff;
+ } else {
+ p[3] = (val >> 24) & 0xff;
+ p[2] = (val >> 16) & 0xff;
+ p[1] = (val >> 8) & 0xff;
+ p[0] = val & 0xff;
+ }
+}
+
+static void get_digest(struct wrg_header *header, char *data, int size)
+{
+ MD5_CTX ctx;
+
+ MD5_Init(&ctx);
+
+ MD5_Update(&ctx, (char *)&header->offset, sizeof(header->offset));
+ MD5_Update(&ctx, (char *)&header->devname, sizeof(header->devname));
+ MD5_Update(&ctx, data, size);
+
+ MD5_Final(header->digest, &ctx);
+}
+
+int main(int argc, char *argv[])
+{
+ struct wrg_header *header;
+ char *buf;
+ struct stat st;
+ int buflen;
+ int err;
+ int res = EXIT_FAILURE;
+
+ FILE *outfile, *infile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "bd:i:o:s:O:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'b':
+ big_endian = 1;
+ break;
+ case 'd':
+ dev_name = optarg;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 's':
+ signature = optarg;
+ break;
+ case 'O':
+ offset = strtoul(optarg, NULL, 0);
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (signature == NULL) {
+ ERR("no signature specified");
+ goto err;
+ }
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto err;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto err;
+ }
+
+ if (dev_name == NULL) {
+ ERR("no device name specified");
+ goto err;
+ }
+
+ err = stat(ifname, &st);
+ if (err){
+ ERRS("stat failed on %s", ifname);
+ goto err;
+ }
+
+ buflen = st.st_size + sizeof(struct wrg_header);
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto err;
+ }
+
+ infile = fopen(ifname, "r");
+ if (infile == NULL) {
+ ERRS("could not open \"%s\" for reading", ifname);
+ goto err_free;
+ }
+
+ errno = 0;
+ fread(buf + sizeof(struct wrg_header), st.st_size, 1, infile);
+ if (errno != 0) {
+ ERRS("unable to read from file %s", ifname);
+ goto close_in;
+ }
+
+ header = (struct wrg_header *) buf;
+ memset(header, '\0', sizeof(struct wrg_header));
+
+ strncpy(header->signature, signature, sizeof(header->signature));
+ strncpy(header->devname, dev_name, sizeof(header->signature));
+ put_u32(&header->magic1, WRG_MAGIC);
+ put_u32(&header->magic2, WRG_MAGIC);
+ put_u32(&header->size, st.st_size);
+ put_u32(&header->offset, offset);
+
+ get_digest(header, buf + sizeof(struct wrg_header), st.st_size);
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto close_in;
+ }
+
+ errno = 0;
+ fwrite(buf, buflen, 1, outfile);
+ if (errno) {
+ ERRS("unable to write to file %s", ofname);
+ goto close_out;
+ }
+
+ fflush(outfile);
+
+ res = EXIT_SUCCESS;
+
+close_out:
+ fclose(outfile);
+ if (res != EXIT_SUCCESS)
+ unlink(ofname);
+close_in:
+ fclose(infile);
+err_free:
+ free(buf);
+err:
+ return res;
+}
diff --git a/tools/firmware-utils/src/mkzcfw.c b/tools/firmware-utils/src/mkzcfw.c
new file mode 100644
index 0000000..2326f1f
--- /dev/null
+++ b/tools/firmware-utils/src/mkzcfw.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "cyg_crc.h"
+
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+# define HOST_TO_BE32(x) (x)
+# define BE32_TO_HOST(x) (x)
+# define HOST_TO_LE32(x) bswap_32(x)
+# define LE32_TO_HOST(x) bswap_32(x)
+#else
+# define HOST_TO_BE32(x) bswap_32(x)
+# define BE32_TO_HOST(x) bswap_32(x)
+# define HOST_TO_LE32(x) (x)
+# define LE32_TO_HOST(x) (x)
+#endif
+
+#define MAGIC_FIRMWARE 0x6d726966 /* 'firm' */
+#define MAGIC_KERNEL 0x676d694b /* 'Kimg' */
+#define MAGIC_ROOTFS 0x676d6952 /* 'Rimg' */
+
+struct file_info {
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+};
+
+struct fw_header {
+ uint32_t magic;
+ uint32_t length;
+ uint32_t unk1;
+ uint32_t unk2;
+} __attribute__ ((packed));
+
+struct fw_tail {
+ uint32_t hw_id;
+ uint32_t crc;
+} __attribute__ ((packed));
+
+struct board_info {
+ char *id;
+ uint32_t hw_id;
+ uint32_t kernel_len;
+ uint32_t rootfs_len;
+};
+
+/*
+ * Globals
+ */
+static char *ofname;
+static char *progname;
+
+static char *board_id;
+static struct board_info *board;
+static struct file_info kernel_info;
+static struct file_info rootfs_info;
+
+
+static struct board_info boards[] = {
+ {
+ .id = "ZCN-1523H-2-8",
+ .hw_id = 0x66661523,
+ .kernel_len = 0x170000,
+ .rootfs_len = 0x610000,
+ }, {
+ .id = "ZCN-1523H-5-16",
+ .hw_id = 0x6615235A,
+ .kernel_len = 0x170000,
+ .rootfs_len = 0x610000,
+ }, {
+ /* terminating entry */
+ }
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define DBG(fmt, ...) do { \
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+static struct board_info *find_board(char *id)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->id != NULL; board++){
+ if (strcasecmp(id, board->id) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+static void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>\n"
+" -k <file> read kernel image from the file <file>\n"
+" -r <file> read rootfs image from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+static int get_file_stat(struct file_info *fdata)
+{
+ struct stat st;
+ int res;
+
+ if (fdata->file_name == NULL)
+ return 0;
+
+ res = stat(fdata->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", fdata->file_name);
+ return res;
+ }
+
+ fdata->file_size = st.st_size;
+ return 0;
+}
+
+static int read_to_buf(struct file_info *fdata, char *buf)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(fdata->file_name, "r");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for reading", fdata->file_name);
+ goto out;
+ }
+
+ errno = 0;
+ fread(buf, fdata->file_size, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file \"%s\"", fdata->file_name);
+ goto out_close;
+ }
+
+ ret = EXIT_SUCCESS;
+
+ out_close:
+ fclose(f);
+ out:
+ return ret;
+}
+
+static int check_options(void)
+{
+ int ret;
+
+ if (board_id == NULL) {
+ ERR("no board specified");
+ return -1;
+ }
+
+ board = find_board(board_id);
+ if (board == NULL) {
+ ERR("unknown/unsupported board id \"%s\"", board_id);
+ return -1;
+ }
+
+ if (kernel_info.file_name == NULL) {
+ ERR("no kernel image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&kernel_info);
+ if (ret)
+ return ret;
+
+ if (kernel_info.file_size > board->kernel_len) {
+ ERR("kernel image is too big");
+ return -1;
+ }
+
+ if (rootfs_info.file_name == NULL) {
+ ERR("no rootfs image specified");
+ return -1;
+ }
+
+ ret = get_file_stat(&rootfs_info);
+ if (ret)
+ return ret;
+
+ if (rootfs_info.file_size > board->rootfs_len) {
+ ERR("rootfs image is too big");
+ return -1;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_fw(char *data, int len)
+{
+ FILE *f;
+ int ret = EXIT_FAILURE;
+
+ f = fopen(ofname, "w");
+ if (f == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ errno = 0;
+ fwrite(data, len, 1, f);
+ if (errno) {
+ ERRS("unable to write output file");
+ goto out_flush;
+ }
+
+ DBG("firmware file \"%s\" completed", ofname);
+
+ ret = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(f);
+ fclose(f);
+ if (ret != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+ out:
+ return ret;
+}
+
+static int build_fw(void)
+{
+ int buflen;
+ char *buf;
+ char *p;
+ int ret = EXIT_FAILURE;
+ int writelen = 0;
+ uint32_t crc;
+ struct fw_header *hdr;
+ struct fw_tail *tail;
+
+ buflen = 3 * sizeof(struct fw_header) +
+ kernel_info.file_size + rootfs_info.file_size +
+ 3 * sizeof(struct fw_tail);
+
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto out;
+ }
+
+ p = buf;
+ memset(p, 0, buflen);
+
+ /* fill firmware header */
+ hdr = (struct fw_header *) p;
+ hdr->magic = HOST_TO_LE32(MAGIC_FIRMWARE);
+ hdr->length = HOST_TO_LE32(buflen - sizeof(struct fw_header));
+ p += sizeof(struct fw_header);
+
+ /* fill kernel block header */
+ hdr = (struct fw_header *) p;
+ hdr->magic = HOST_TO_LE32(MAGIC_KERNEL);
+ hdr->length = HOST_TO_LE32(kernel_info.file_size +
+ sizeof(struct fw_tail));
+ p += sizeof(struct fw_header);
+
+ /* read kernel data */
+ ret = read_to_buf(&kernel_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ /* fill firmware tail */
+ tail = (struct fw_tail *) (p + kernel_info.file_size);
+ tail->hw_id = HOST_TO_BE32(board->hw_id);
+ tail->crc = HOST_TO_BE32(cyg_crc32(p, kernel_info.file_size +
+ sizeof(struct fw_tail) - 4));
+
+ p += kernel_info.file_size + sizeof(struct fw_tail);
+
+ /* fill rootfs block header */
+ hdr = (struct fw_header *) p;
+ hdr->magic = HOST_TO_LE32(MAGIC_ROOTFS);
+ hdr->length = HOST_TO_LE32(rootfs_info.file_size +
+ sizeof(struct fw_tail));
+ p += sizeof(struct fw_header);
+
+ /* read rootfs data */
+ ret = read_to_buf(&rootfs_info, p);
+ if (ret)
+ goto out_free_buf;
+
+ /* fill firmware tail */
+ tail = (struct fw_tail *) (p + rootfs_info.file_size);
+ tail->hw_id = HOST_TO_BE32(board->hw_id);
+ tail->crc = HOST_TO_BE32(cyg_crc32(p, rootfs_info.file_size +
+ sizeof(struct fw_tail) - 4));
+
+ p += rootfs_info.file_size + sizeof(struct fw_tail);
+
+ /* fill firmware tail */
+ tail = (struct fw_tail *) p;
+ tail->hw_id = HOST_TO_BE32(board->hw_id);
+ tail->crc = HOST_TO_BE32(cyg_crc32(buf + sizeof(struct fw_header),
+ buflen - sizeof(struct fw_header) - 4));
+
+ ret = write_fw(buf, buflen);
+ if (ret)
+ goto out_free_buf;
+
+ ret = EXIT_SUCCESS;
+
+ out_free_buf:
+ free(buf);
+ out:
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_FAILURE;
+ int err;
+
+ FILE *outfile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "B:k:r:o:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'B':
+ board_id = optarg;
+ break;
+ case 'k':
+ kernel_info.file_name = optarg;
+ break;
+ case 'r':
+ rootfs_info.file_name = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ ret = check_options();
+ if (ret)
+ goto out;
+
+ ret = build_fw();
+
+ out:
+ return ret;
+}
+
diff --git a/tools/firmware-utils/src/mkzynfw.c b/tools/firmware-utils/src/mkzynfw.c
new file mode 100644
index 0000000..ccbabfe
--- /dev/null
+++ b/tools/firmware-utils/src/mkzynfw.c
@@ -0,0 +1,1131 @@
+/*
+ *
+ * Copyright (C) 2007-2008 OpenWrt.org
+ * Copyright (C) 2007-2008 Gabor Juhos <juhosg at openwrt.org>
+ *
+ * This code was based on the information of the ZyXEL's firmware
+ * image format written by Kolja Waschk, can be found at:
+ * http://www.ixo.de/info/zyxel_uclinux
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <endian.h> /* for __BYTE_ORDER */
+#if defined(__CYGWIN__)
+# include <byteswap.h>
+#endif
+#include <inttypes.h>
+
+#include "zynos.h"
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define HOST_TO_LE16(x) (x)
+# define HOST_TO_LE32(x) (x)
+# define LE16_TO_HOST(x) (x)
+# define LE32_TO_HOST(x) (x)
+# define HOST_TO_BE16(x) bswap_16(x)
+# define HOST_TO_BE32(x) bswap_32(x)
+# define BE16_TO_HOST(x) bswap_16(x)
+# define BE32_TO_HOST(x) bswap_32(x)
+#else
+# define HOST_TO_BE16(x) (x)
+# define HOST_TO_BE32(x) (x)
+# define BE16_TO_HOST(x) (x)
+# define BE32_TO_HOST(x) (x)
+# define HOST_TO_LE16(x) bswap_16(x)
+# define HOST_TO_LE32(x) bswap_32(x)
+# define LE16_TO_HOST(x) bswap_16(x)
+# define LE32_TO_HOST(x) bswap_32(x)
+#endif
+
+#define ALIGN(x,y) (((x)+((y)-1)) & ~((y)-1))
+
+#define MAX_NUM_BLOCKS 8
+#define MAX_ARG_COUNT 32
+#define MAX_ARG_LEN 1024
+#define FILE_BUF_LEN (16*1024)
+
+
+struct csum_state{
+ int odd;
+ uint32_t sum;
+ uint32_t tmp;
+};
+
+struct fw_block {
+ uint32_t align; /* alignment of this block */
+ char *file_name; /* name of the file */
+ uint32_t file_size; /* length of the file */
+ char *mmap_name; /* name in the MMAP table */
+ int type; /* block type */
+ uint32_t padlen;
+ uint8_t padc;
+};
+
+#define BLOCK_TYPE_BOOTEXT 0
+#define BLOCK_TYPE_RAW 1
+
+struct fw_mmap {
+ uint32_t addr;
+ uint32_t size;
+ uint32_t user_addr;
+ uint32_t user_size;
+};
+#define MMAP_DATA_SIZE 1024
+#define MMAP_ALIGN 16
+
+struct board_info {
+ char *name; /* model name */
+ char *desc; /* description */
+ uint16_t vendor; /* vendor id */
+ uint16_t model; /* model id */
+ uint32_t flash_base; /* flash base address */
+ uint32_t flash_size; /* board flash size */
+ uint32_t code_start; /* code start address */
+ uint32_t romio_offs; /* offset of the firmware within the flash */
+ uint32_t bootext_size; /* maximum size of bootext block */
+};
+
+/*
+ * Globals
+ */
+char *progname;
+char *ofname = NULL;
+int verblevel = 0;
+
+struct board_info *board = NULL;
+
+struct fw_block blocks[MAX_NUM_BLOCKS];
+struct fw_block *bootext_block = NULL;
+int num_blocks = 0;
+
+#define ADM5120_FLASH_BASE 0xBFC00000
+#define ADM5120_CODE_START 0x80008000
+
+/* TODO: check values for AR7 */
+#define AR7_FLASH_BASE 0xB0000000
+#define AR7_CODE_START 0x94008000
+
+#define ATHEROS_FLASH_BASE 0xBFC00000
+#define ATHEROS_CODE_START 0x80e00000
+
+#define AR71XX_FLASH_BASE 0xBFC00000
+#define AR71XX_CODE_START 0x81E00000
+
+#define BOARD(n, d, v, m, fb, fs, cs, fo) { \
+ .name = (n), .desc=(d), \
+ .vendor = (v), .model = (m), \
+ .flash_base = (fb), .flash_size = (fs)<<20, \
+ .code_start = (cs), .romio_offs = (fo), \
+ .bootext_size = BOOTEXT_DEF_SIZE \
+ }
+
+#define ADMBOARD1(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \
+ ADM5120_FLASH_BASE, fs, ADM5120_CODE_START, 0x8000)
+
+#define ADMBOARD2(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \
+ ADM5120_FLASH_BASE, fs, ADM5120_CODE_START, 0x10000)
+
+#define AR7BOARD1(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \
+ AR7_FLASH_BASE, fs, AR7_CODE_START, 0x8000)
+
+#define ATHEROSBOARD1(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \
+ ATHEROS_FLASH_BASE, fs, ATHEROS_CODE_START, 0x30000)
+
+#define AR71XXBOARD1(n, d, m, fs) { \
+ .name = (n), .desc=(d), \
+ .vendor = (ZYNOS_VENDOR_ID_ZYXEL), .model = (m), \
+ .flash_base = (AR71XX_FLASH_BASE), .flash_size = (fs)<<20, \
+ .code_start = (AR71XX_CODE_START), .romio_offs = (0x40000), \
+ .bootext_size = 0x30000 \
+ }
+
+
+static struct board_info boards[] = {
+ /*
+ * Infineon/ADMtek ADM5120 based boards
+ */
+ ADMBOARD2("ES-2024A", "ZyXEL ES-2024A", ZYNOS_MODEL_ES_2024A, 4),
+ ADMBOARD2("ES-2024PWR", "ZyXEL ES-2024PWR", ZYNOS_MODEL_ES_2024PWR, 4),
+ ADMBOARD2("ES-2108", "ZyXEL ES-2108", ZYNOS_MODEL_ES_2108, 4),
+ ADMBOARD2("ES-2108-F", "ZyXEL ES-2108-F", ZYNOS_MODEL_ES_2108_F, 4),
+ ADMBOARD2("ES-2108-G", "ZyXEL ES-2108-G", ZYNOS_MODEL_ES_2108_G, 4),
+ ADMBOARD2("ES-2108-LC", "ZyXEL ES-2108-LC", ZYNOS_MODEL_ES_2108_LC, 4),
+ ADMBOARD2("ES-2108PWR", "ZyXEL ES-2108PWR", ZYNOS_MODEL_ES_2108PWR, 4),
+ ADMBOARD1("HS-100", "ZyXEL HomeSafe 100", ZYNOS_MODEL_HS_100, 2),
+ ADMBOARD1("HS-100W", "ZyXEL HomeSafe 100W", ZYNOS_MODEL_HS_100W, 2),
+ ADMBOARD1("P-334", "ZyXEL Prestige 334", ZYNOS_MODEL_P_334, 2),
+ ADMBOARD1("P-334U", "ZyXEL Prestige 334U", ZYNOS_MODEL_P_334U, 4),
+ ADMBOARD1("P-334W", "ZyXEL Prestige 334W", ZYNOS_MODEL_P_334W, 2),
+ ADMBOARD1("P-334WH", "ZyXEL Prestige 334WH", ZYNOS_MODEL_P_334WH, 4),
+ ADMBOARD1("P-334WHD", "ZyXEL Prestige 334WHD", ZYNOS_MODEL_P_334WHD, 4),
+ ADMBOARD1("P-334WT", "ZyXEL Prestige 334WT", ZYNOS_MODEL_P_334WT, 4),
+ ADMBOARD1("P-335", "ZyXEL Prestige 335", ZYNOS_MODEL_P_335, 4),
+ ADMBOARD1("P-335Plus", "ZyXEL Prestige 335Plus", ZYNOS_MODEL_P_335PLUS, 4),
+ ADMBOARD1("P-335U", "ZyXEL Prestige 335U", ZYNOS_MODEL_P_335U, 4),
+ ADMBOARD1("P-335WT", "ZyXEL Prestige 335WT", ZYNOS_MODEL_P_335WT, 4),
+
+ {
+ .name = "P-2602HW-D1A",
+ .desc = "ZyXEL P-2602HW-D1A",
+ .vendor = ZYNOS_VENDOR_ID_ZYXEL,
+ .model = ZYNOS_MODEL_P_2602HW_D1A,
+ .flash_base = AR7_FLASH_BASE,
+ .flash_size = 4*1024*1024,
+ .code_start = 0x94008000,
+ .romio_offs = 0x20000,
+ .bootext_size = BOOTEXT_DEF_SIZE,
+ },
+
+#if 0
+ /*
+ * Texas Instruments AR7 based boards
+ */
+ AR7BOARD1("P-660H-61", "ZyXEL P-660H-61", ZYNOS_MODEL_P_660H_61, 2),
+ AR7BOARD1("P-660H-63", "ZyXEL P-660H-63", ZYNOS_MODEL_P_660H_63, 2),
+ AR7BOARD1("P-660H-D1", "ZyXEL P-660H-D1", ZYNOS_MODEL_P_660H_D1, 2),
+ AR7BOARD1("P-660H-D3", "ZyXEL P-660H-D3", ZYNOS_MODEL_P_660H_D3, 2),
+ AR7BOARD1("P-660HW-61", "ZyXEL P-660HW-61", ZYNOS_MODEL_P_660HW_61, 2),
+ AR7BOARD1("P-660HW-63", "ZyXEL P-660HW-63", ZYNOS_MODEL_P_660HW_63, 2),
+ AR7BOARD1("P-660HW-67", "ZyXEL P-660HW-67", ZYNOS_MODEL_P_660HW_67, 2),
+ AR7BOARD1("P-660HW-D1", "ZyXEL P-660HW-D1", ZYNOS_MODEL_P_660HW_D1, 2),
+ AR7BOARD1("P-660HW-D3", "ZyXEL P-660HW-D3", ZYNOS_MODEL_P_660HW_D3, 2),
+ AR7BOARD1("P-660R-61", "ZyXEL P-660R-61", ZYNOS_MODEL_P_660R_61, 2),
+ AR7BOARD1("P-660R-61C", "ZyXEL P-660R-61C", ZYNOS_MODEL_P_660R_61C, 2),
+ AR7BOARD1("P-660R-63", "ZyXEL P-660R-63", ZYNOS_MODEL_P_660R_63, 2),
+ AR7BOARD1("P-660R-63C", "ZyXEL P-660R-63C", ZYNOS_MODEL_P_660R_63C, 2),
+ AR7BOARD1("P-660R-67", "ZyXEL P-660R-67", ZYNOS_MODEL_P_660R_67, 2),
+ AR7BOARD1("P-660R-D1", "ZyXEL P-660R-D1", ZYNOS_MODEL_P_660R_D1, 2),
+ AR7BOARD1("P-660R-D3", "ZyXEL P-660R-D3", ZYNOS_MODEL_P_660R_D3, 2),
+#endif
+ {
+ .name = "O2SURF",
+ .desc = "O2 DSL Surf & Phone",
+ .vendor = ZYNOS_VENDOR_ID_O2,
+ .model = ZYNOS_MODEL_O2SURF,
+ .flash_base = AR7_FLASH_BASE,
+ .flash_size = 8*1024*1024,
+ .code_start = 0x94014000,
+ .romio_offs = 0x40000,
+ .bootext_size = BOOTEXT_DEF_SIZE,
+ },
+
+ /*
+:x
+ */
+ ATHEROSBOARD1("NBG-318S", "ZyXEL NBG-318S", ZYNOS_MODEL_NBG_318S, 4),
+
+ /*
+ * Atheros ar71xx based boards
+ */
+ AR71XXBOARD1("NBG-460N", "ZyXEL NBG-460N", ZYNOS_MODEL_NBG_460N, 4),
+
+ {.name = NULL}
+};
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define WARN(fmt, ...) do { \
+ fprintf(stderr, "[%s] *** warning: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define DBG(lev, fmt, ...) do { \
+ if (verblevel < lev) \
+ break;\
+ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERR_FATAL -1
+#define ERR_INVALID_IMAGE -2
+
+/*
+ * Helper routines
+ */
+void
+usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -B <board> create image for the board specified with <board>.\n"
+" valid <board> values:\n"
+ );
+ for (board = boards; board->name != NULL; board++){
+ fprintf(stream,
+" %-12s= %s\n",
+ board->name, board->desc);
+ };
+ fprintf(stream,
+" -b <file>[:<align>]\n"
+" add boot extension block to the image\n"
+" -r <file>[:<align>]\n"
+" add raw block to the image\n"
+" -o <file> write output to the file <file>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+
+/*
+ * argument parsing
+ */
+int
+str2u32(char *arg, uint32_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err)) {
+ return -1;
+ }
+
+ *val = t;
+ return 0;
+}
+
+
+int
+str2u16(char *arg, uint16_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) {
+ return -1;
+ }
+
+ *val = t & 0xFFFF;
+ return 0;
+}
+
+int
+str2u8(char *arg, uint8_t *val)
+{
+ char *err = NULL;
+ uint32_t t;
+
+ errno=0;
+ t = strtoul(arg, &err, 0);
+ if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) {
+ return -1;
+ }
+
+ *val = t & 0xFF;
+ return 0;
+}
+
+int
+str2sig(char *arg, uint32_t *sig)
+{
+ if (strlen(arg) != 4)
+ return -1;
+
+ *sig = arg[0] | (arg[1] << 8) | (arg[2] << 16) | (arg[3] << 24);
+
+ return 0;
+}
+
+
+int
+parse_arg(char *arg, char *buf, char *argv[])
+{
+ int res = 0;
+ size_t argl;
+ char *tok;
+ char **ap = &buf;
+ int i;
+
+ memset(argv, 0, MAX_ARG_COUNT * sizeof(void *));
+
+ if ((arg == NULL)) {
+ /* no arguments */
+ return 0;
+ }
+
+ argl = strlen(arg);
+ if (argl == 0) {
+ /* no arguments */
+ return 0;
+ }
+
+ if (argl >= MAX_ARG_LEN) {
+ /* argument is too long */
+ argl = MAX_ARG_LEN-1;
+ }
+
+ memcpy(buf, arg, argl);
+ buf[argl] = '\0';
+
+ for (i = 0; i < MAX_ARG_COUNT; i++) {
+ tok = strsep(ap, ":");
+ if (tok == NULL) {
+ break;
+ }
+#if 0
+ else if (tok[0] == '\0') {
+ break;
+ }
+#endif
+ argv[i] = tok;
+ res++;
+ }
+
+ return res;
+}
+
+
+int
+required_arg(char c, char *arg)
+{
+ if (arg == NULL || *arg != '-')
+ return 0;
+
+ ERR("option -%c requires an argument\n", c);
+ return -1;
+}
+
+
+int
+is_empty_arg(char *arg)
+{
+ int ret = 1;
+ if (arg != NULL) {
+ if (*arg) ret = 0;
+ };
+ return ret;
+}
+
+
+void
+csum_init(struct csum_state *css)
+{
+ css->odd = 0;
+ css->sum = 0;
+ css->tmp = 0;
+}
+
+
+void
+csum_update(uint8_t *p, uint32_t len, struct csum_state *css)
+{
+ if (len == 0)
+ return;
+
+ if (css->odd) {
+ css->sum += (css->tmp << 8) + p[0];
+ if (css->sum > 0xFFFF) {
+ css->sum += 1;
+ css->sum &= 0xFFFF;
+ }
+ css->odd = 0;
+ len--;
+ p++;
+ }
+
+ for ( ; len > 1; len -= 2, p +=2 ) {
+ css->sum += (p[0] << 8) + p[1];
+ if (css->sum > 0xFFFF) {
+ css->sum += 1;
+ css->sum &= 0xFFFF;
+ }
+ }
+
+ if (len == 1){
+ css->tmp = p[0];
+ css->odd = 1;
+ }
+}
+
+
+uint16_t
+csum_get(struct csum_state *css)
+{
+ char pad = 0;
+
+ csum_update(&pad, 1, css);
+ return css->sum;
+}
+
+uint16_t
+csum_buf(uint8_t *p, uint32_t len)
+{
+ struct csum_state css;
+
+ csum_init(&css);
+ csum_update(p, len, &css);
+ return csum_get(&css);
+
+}
+
+/*
+ * routines to write data to the output file
+ */
+int
+write_out_data(FILE *outfile, uint8_t *data, size_t len,
+ struct csum_state *css)
+{
+ errno = 0;
+
+ fwrite(data, len, 1, outfile);
+ if (errno) {
+ ERR("unable to write output file");
+ return -1;
+ }
+
+ if (css) {
+ csum_update(data, len, css);
+ }
+
+ return 0;
+}
+
+
+int
+write_out_padding(FILE *outfile, size_t len, uint8_t padc,
+ struct csum_state *css)
+{
+ uint8_t buf[512];
+ size_t buflen = sizeof(buf);
+
+ memset(buf, padc, buflen);
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ if (write_out_data(outfile, buf, buflen, css))
+ return -1;
+
+ len -= buflen;
+ }
+
+ return 0;
+}
+
+
+int
+write_out_data_align(FILE *outfile, uint8_t *data, size_t len, size_t align,
+ struct csum_state *css)
+{
+ size_t padlen;
+ int res;
+
+ res = write_out_data(outfile, data, len, css);
+ if (res)
+ return res;
+
+ padlen = ALIGN(len,align) - len;
+ res = write_out_padding(outfile, padlen, 0xFF, css);
+
+ return res;
+}
+
+
+int
+write_out_header(FILE *outfile, struct zyn_rombin_hdr *hdr)
+{
+ struct zyn_rombin_hdr t;
+
+ errno = 0;
+ if (fseek(outfile, 0, SEEK_SET) != 0) {
+ ERRS("fseek failed on output file");
+ return -1;
+ }
+
+ /* setup temporary header fields */
+ memset(&t, 0, sizeof(t));
+ t.addr = HOST_TO_BE32(hdr->addr);
+ memcpy(&t.sig, ROMBIN_SIGNATURE, ROMBIN_SIG_LEN);
+ t.type = hdr->type;
+ t.flags = hdr->flags;
+ t.osize = HOST_TO_BE32(hdr->osize);
+ t.csize = HOST_TO_BE32(hdr->csize);
+ t.ocsum = HOST_TO_BE16(hdr->ocsum);
+ t.ccsum = HOST_TO_BE16(hdr->ccsum);
+ t.mmap_addr = HOST_TO_BE32(hdr->mmap_addr);
+
+ DBG(2, "hdr.addr = 0x%08x", hdr->addr);
+ DBG(2, "hdr.type = 0x%02x", hdr->type);
+ DBG(2, "hdr.osize = 0x%08x", hdr->osize);
+ DBG(2, "hdr.csize = 0x%08x", hdr->csize);
+ DBG(2, "hdr.flags = 0x%02x", hdr->flags);
+ DBG(2, "hdr.ocsum = 0x%04x", hdr->ocsum);
+ DBG(2, "hdr.ccsum = 0x%04x", hdr->ccsum);
+ DBG(2, "hdr.mmap_addr = 0x%08x", hdr->mmap_addr);
+
+ return write_out_data(outfile, (uint8_t *)&t, sizeof(t), NULL);
+}
+
+
+int
+write_out_mmap(FILE *outfile, struct fw_mmap *mmap, struct csum_state *css)
+{
+ struct zyn_mmt_hdr *mh;
+ uint8_t buf[MMAP_DATA_SIZE];
+ uint32_t user_size;
+ char *data;
+ int res;
+
+ memset(buf, 0, sizeof(buf));
+
+ mh = (struct zyn_mmt_hdr *)buf;
+
+ /* TODO: needs to recreate the memory map too? */
+ mh->count=0;
+
+ /* Build user data section */
+ data = buf+sizeof(*mh);
+ data += sprintf(data, "Vendor 1 %d", board->vendor);
+ *data++ = '\0';
+ data += sprintf(data, "Model 1 %d", BE16_TO_HOST(board->model));
+ *data++ = '\0';
+ /* TODO: make hardware version configurable? */
+ data += sprintf(data, "HwVerRange 2 %d %d", 0, 0);
+ *data++ = '\0';
+
+ user_size = (uint8_t *)data - buf;
+ mh->user_start= HOST_TO_BE32(mmap->addr+sizeof(*mh));
+ mh->user_end= HOST_TO_BE32(mmap->addr+user_size);
+ mh->csum = HOST_TO_BE16(csum_buf(buf+sizeof(*mh), user_size));
+
+ res = write_out_data(outfile, buf, sizeof(buf), css);
+
+ return res;
+}
+
+
+int
+block_stat_file(struct fw_block *block)
+{
+ struct stat st;
+ int res;
+
+ if (block->file_name == NULL)
+ return 0;
+
+ res = stat(block->file_name, &st);
+ if (res){
+ ERRS("stat failed on %s", block->file_name);
+ return res;
+ }
+
+ block->file_size = st.st_size;
+ return 0;
+}
+
+
+int
+read_magic(uint16_t *magic)
+{
+ FILE *f;
+ int res;
+
+ errno = 0;
+ f = fopen(bootext_block->file_name,"r");
+ if (errno) {
+ ERRS("unable to open file: %s", bootext_block->file_name);
+ return -1;
+ }
+
+ errno = 0;
+ fread(magic, 2, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file: %s", bootext_block->file_name);
+ res = -1;
+ goto err;
+ }
+
+ res = 0;
+
+err:
+ fclose(f);
+ return res;
+}
+
+
+int
+write_out_file(FILE *outfile, char *name, size_t len, struct csum_state *css)
+{
+ char buf[FILE_BUF_LEN];
+ size_t buflen = sizeof(buf);
+ FILE *f;
+ int res;
+
+ DBG(2, "writing out file, name=%s, len=%zu",
+ name, len);
+
+ errno = 0;
+ f = fopen(name,"r");
+ if (errno) {
+ ERRS("unable to open file: %s", name);
+ return -1;
+ }
+
+ while (len > 0) {
+ if (len < buflen)
+ buflen = len;
+
+ /* read data from source file */
+ errno = 0;
+ fread(buf, buflen, 1, f);
+ if (errno != 0) {
+ ERRS("unable to read from file: %s",name);
+ res = -1;
+ break;
+ }
+
+ res = write_out_data(outfile, buf, buflen, css);
+ if (res)
+ break;
+
+ len -= buflen;
+ }
+
+ fclose(f);
+ return res;
+}
+
+
+int
+write_out_block(FILE *outfile, struct fw_block *block, struct csum_state *css)
+{
+ int res;
+
+ if (block == NULL)
+ return 0;
+
+ if (block->file_name == NULL)
+ return 0;
+
+ if (block->file_size == 0)
+ return 0;
+
+ res = write_out_file(outfile, block->file_name,
+ block->file_size, css);
+ return res;
+}
+
+
+int
+write_out_image(FILE *outfile)
+{
+ struct fw_block *block;
+ struct fw_mmap mmap;
+ struct zyn_rombin_hdr hdr;
+ struct csum_state css;
+ int i, res;
+ uint32_t offset;
+ uint32_t padlen;
+ uint16_t csum;
+ uint16_t t;
+
+ /* setup header fields */
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.addr = board->code_start;
+ hdr.type = OBJECT_TYPE_BOOTEXT;
+ hdr.flags = ROMBIN_FLAG_OCSUM;
+
+ offset = board->romio_offs;
+
+ res = write_out_header(outfile, &hdr);
+ if (res)
+ return res;
+
+ offset += sizeof(hdr);
+
+ csum_init(&css);
+ res = write_out_block(outfile, bootext_block, &css);
+ if (res)
+ return res;
+
+ offset += bootext_block->file_size;
+ if (offset > (board->romio_offs + board->bootext_size)) {
+ ERR("bootext file '%s' is too big", bootext_block->file_name);
+ return -1;
+ }
+
+ padlen = ALIGN(offset, MMAP_ALIGN) - offset;
+ res = write_out_padding(outfile, padlen, 0xFF, &css);
+ if (res)
+ return res;
+
+ offset += padlen;
+
+ mmap.addr = board->flash_base + offset;
+ res = write_out_mmap(outfile, &mmap, &css);
+ if (res)
+ return res;
+
+ offset += MMAP_DATA_SIZE;
+
+ if ((offset - board->romio_offs) < board->bootext_size) {
+ padlen = board->romio_offs + board->bootext_size - offset;
+ res = write_out_padding(outfile, padlen, 0xFF, &css);
+ if (res)
+ return res;
+ offset += padlen;
+
+ DBG(2, "bootext end at %08x", offset);
+ }
+
+ for (i = 0; i < num_blocks; i++) {
+ block = &blocks[i];
+
+ if (block->type == BLOCK_TYPE_BOOTEXT)
+ continue;
+
+ padlen = ALIGN(offset, block->align) - offset;
+ res = write_out_padding(outfile, padlen, 0xFF, &css);
+ if (res)
+ return res;
+ offset += padlen;
+
+ res = write_out_block(outfile, block, &css);
+ if (res)
+ return res;
+ offset += block->file_size;
+ }
+
+ padlen = ALIGN(offset, 4) - offset;
+ res = write_out_padding(outfile, padlen, 0xFF, &css);
+ if (res)
+ return res;
+ offset += padlen;
+
+ csum = csum_get(&css);
+ hdr.mmap_addr = mmap.addr;
+ hdr.osize = 2;
+
+ res = read_magic(&hdr.ocsum);
+ if (res)
+ return res;
+ hdr.ocsum = BE16_TO_HOST(hdr.ocsum);
+
+ if (csum <= hdr.ocsum)
+ t = hdr.ocsum - csum;
+ else
+ t = hdr.ocsum - csum - 1;
+
+ DBG(2, "ocsum=%04x, csum=%04x, fix=%04x", hdr.ocsum, csum, t);
+
+ t = HOST_TO_BE16(t);
+ res = write_out_data(outfile, (uint8_t *)&t, 2, NULL);
+ if (res)
+ return res;
+
+
+ res = write_out_header(outfile, &hdr);
+
+ return res;
+}
+
+
+struct board_info *
+find_board(char *name)
+{
+ struct board_info *ret;
+ struct board_info *board;
+
+ ret = NULL;
+ for (board = boards; board->name != NULL; board++){
+ if (strcasecmp(name, board->name) == 0) {
+ ret = board;
+ break;
+ }
+ };
+
+ return ret;
+}
+
+
+int
+parse_opt_board(char ch, char *arg)
+{
+
+ DBG(1,"parsing board option: -%c %s", ch, arg);
+
+ if (board != NULL) {
+ ERR("only one board option allowed");
+ return -1;
+ }
+
+ if (required_arg(ch, arg))
+ return -1;
+
+ board = find_board(arg);
+ if (board == NULL){
+ ERR("invalid/unknown board specified: %s", arg);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+parse_opt_ofname(char ch, char *arg)
+{
+
+ if (ofname != NULL) {
+ ERR("only one output file allowed");
+ return -1;
+ }
+
+ if (required_arg(ch, arg))
+ return -1;
+
+ ofname = arg;
+
+ return 0;
+}
+
+
+int
+parse_opt_block(char ch, char *arg)
+{
+ char buf[MAX_ARG_LEN];
+ char *argv[MAX_ARG_COUNT];
+ int argc;
+ char *p;
+ struct fw_block *block;
+ int i;
+
+ if ( num_blocks >= MAX_NUM_BLOCKS ) {
+ ERR("too many blocks specified");
+ return -1;
+ }
+
+ block = &blocks[num_blocks++];
+
+ /* setup default field values */
+ block->padc = 0xFF;
+
+ switch(ch) {
+ case 'b':
+ if (bootext_block) {
+ ERR("only one boot extension block allowed");
+ break;
+ }
+ block->type = BLOCK_TYPE_BOOTEXT;
+ bootext_block = block;
+ break;
+ case 'r':
+ block->type = BLOCK_TYPE_RAW;
+ break;
+ }
+
+ argc = parse_arg(arg, buf, argv);
+
+ i = 0;
+ p = argv[i++];
+ if (is_empty_arg(p)) {
+ ERR("no file specified in %s", arg);
+ return -1;
+ } else {
+ block->file_name = strdup(p);
+ if (block->file_name == NULL) {
+ ERR("not enough memory");
+ return -1;
+ }
+ }
+
+ if (block->type == BLOCK_TYPE_BOOTEXT)
+ return 0;
+
+ p = argv[i++];
+ if (!is_empty_arg(p)) {
+ if (str2u32(p, &block->align) != 0) {
+ ERR("invalid block align in %s", arg);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+int
+calc_block_offsets(int type, uint32_t *offset)
+{
+ struct fw_block *block;
+ uint32_t next_offs;
+ uint32_t avail;
+ int i, res;
+
+ DBG(1,"calculating block offsets, starting with %" PRIu32,
+ *offset);
+
+ res = 0;
+ for (i = 0; i < num_blocks; i++) {
+ block = &blocks[i];
+
+ if (block->type != type)
+ continue;
+
+ next_offs = ALIGN(*offset, block->align);
+ avail = board->flash_size - next_offs;
+ if (block->file_size > avail) {
+ ERR("file %s is too big, offset = %u, size=%u,"
+ " avail = %u, align = %u", block->file_name,
+ (unsigned)next_offs,
+ (unsigned)block->file_size,
+ (unsigned)avail,
+ (unsigned)block->align);
+ res = -1;
+ break;
+ }
+
+ block->padlen = next_offs - *offset;
+ *offset += block->file_size;
+ }
+
+ return res;
+}
+
+int
+process_blocks(void)
+{
+ struct fw_block *block;
+ uint32_t offset;
+ int i;
+ int res;
+
+ /* collecting file stats */
+ for (i = 0; i < num_blocks; i++) {
+ block = &blocks[i];
+ res = block_stat_file(block);
+ if (res)
+ return res;
+ }
+
+ offset = board->romio_offs + bootext_block->file_size;
+ res = calc_block_offsets(BLOCK_TYPE_RAW, &offset);
+
+ return res;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int optinvalid = 0; /* flag for invalid option */
+ int c;
+ int res = EXIT_FAILURE;
+
+ FILE *outfile;
+
+ progname=basename(argv[0]);
+
+ opterr = 0; /* could not print standard getopt error messages */
+ while ( 1 ) {
+ optinvalid = 0;
+
+ c = getopt(argc, argv, "b:B:ho:r:v");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'b':
+ case 'r':
+ optinvalid = parse_opt_block(c,optarg);
+ break;
+ case 'B':
+ optinvalid = parse_opt_board(c,optarg);
+ break;
+ case 'o':
+ optinvalid = parse_opt_ofname(c,optarg);
+ break;
+ case 'v':
+ verblevel++;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ optinvalid = 1;
+ break;
+ }
+ if (optinvalid != 0 ) {
+ ERR("invalid option: -%c", optopt);
+ goto out;
+ }
+ }
+
+ if (board == NULL) {
+ ERR("no board specified");
+ goto out;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto out;
+ }
+
+ if (optind < argc) {
+ ERR("invalid option: %s", argv[optind]);
+ goto out;
+ }
+
+ if (process_blocks() != 0) {
+ goto out;
+ }
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto out;
+ }
+
+ if (write_out_image(outfile) != 0)
+ goto out_flush;
+
+ DBG(1,"Image file %s completed.", ofname);
+
+ res = EXIT_SUCCESS;
+
+out_flush:
+ fflush(outfile);
+ fclose(outfile);
+ if (res != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+out:
+ return res;
+}
diff --git a/tools/firmware-utils/src/motorola-bin.c b/tools/firmware-utils/src/motorola-bin.c
new file mode 100644
index 0000000..fecb4ce
--- /dev/null
+++ b/tools/firmware-utils/src/motorola-bin.c
@@ -0,0 +1,227 @@
+/*
+ * motorola-bin.c
+ *
+ * Copyright (C) 2005-2006 Mike Baker,
+ * Imre Kaloz <kaloz@openwrt.org>
+ * D. Hugh Redelmeier
+ * OpenWrt.org
+ *
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*
+ * Motorola's firmware flashing code requires an extra header.
+ * The header is eight bytes (see struct motorola below).
+ * This program will take a firmware file and create a new one
+ * with this header:
+ * motorola-bin --wr850g WR850G_V403.stripped.trx WR850G_V403.trx
+ *
+ * Note: Motorola's firmware is distributed with this header.
+ * If you need to flash Motorola firmware on a router running OpenWRT,
+ * you will to remove this header. Use the --strip flag:
+ * motorola-bin --strip WR850G_V403.trx WR850G_V403.stripped.trx
+ */
+
+/*
+ * February 1, 2006
+ *
+ * Add support for for creating WA840G and WE800G images
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#define BPB 8 /* bits/byte */
+
+static uint32_t crc32[1<<BPB];
+
+static void init_crc32()
+{
+ const uint32_t poly = ntohl(0x2083b8ed);
+ int n;
+
+ for (n = 0; n < 1<<BPB; n++) {
+ uint32_t crc = n;
+ int bit;
+
+ for (bit = 0; bit < BPB; bit++)
+ crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
+ crc32[n] = crc;
+ }
+}
+
+static uint32_t crc32buf(unsigned char *buf, size_t len)
+{
+ uint32_t crc = 0xFFFFFFFF;
+
+ for (; len; len--, buf++)
+ crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB);
+ return crc;
+}
+
+struct motorola {
+ uint32_t crc; // crc32 of the remainder
+ uint32_t flags; // unknown, 105770*
+};
+
+static const struct model {
+ char digit; /* a digit signifying model (historical) */
+ const char *name;
+ uint32_t flags;
+} models[] = {
+ { '1', "WR850G", 0x10577050LU },
+ { '2', "WA840G", 0x10577040LU },
+ { '3', "WE800G", 0x10577000LU },
+ { '\0', NULL, 0 }
+};
+
+static void usage(const char *) __attribute__ (( __noreturn__ ));
+
+static void usage(const char *mess)
+{
+ const struct model *m;
+
+ fprintf(stderr, "Error: %s\n", mess);
+ fprintf(stderr, "Usage: motorola-bin -device|--strip infile outfile\n");
+ fprintf(stderr, "Known devices: ");
+
+ for (m = models; m->digit != '\0'; m++)
+ fprintf(stderr, " %c - %s", m->digit, m->name);
+
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ off_t len; // of original firmware
+ int fd;
+ void *trx; // pointer to original firmware (mmmapped)
+ struct motorola *firmware; // pionter to prefix + copy of original firmware
+ uint32_t flags;
+
+ // verify parameters
+
+ if (argc != 4)
+ usage("wrong number of arguments");
+
+ // mmap trx file
+ if ((fd = open(argv[2], O_RDONLY)) < 0
+ || (len = lseek(fd, 0, SEEK_END)) < 0
+ || (trx = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1)
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error loading file %s: %s\n", argv[2], strerror(errno));
+ exit(1);
+ }
+
+ init_crc32();
+
+ if (strcmp(argv[1], "--strip") == 0)
+ {
+ const char *ugh = NULL;
+
+ if (len < sizeof(struct motorola)) {
+ ugh = "input file too short";
+ } else {
+ const struct model *m;
+
+ firmware = trx;
+ if (htonl(crc32buf(trx + offsetof(struct motorola, flags), len - offsetof(struct motorola, flags))) != firmware->crc)
+ ugh = "Invalid CRC";
+ for (m = models; ; m++) {
+ if (m->digit == '\0') {
+ if (ugh == NULL)
+ ugh = "unrecognized flags field";
+ break;
+ }
+ if (firmware->flags == htonl(m->flags)) {
+ fprintf(stderr, "Firmware for Motorola %s\n", m->name);
+ break;
+ }
+ }
+ }
+
+ if (ugh != NULL) {
+ fprintf(stderr, "%s\n", ugh);
+ exit(3);
+ } else {
+ // all is well, write the file without the prefix
+ if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0
+ || write(fd, trx + sizeof(struct motorola), len - sizeof(struct motorola)) != len - sizeof(struct motorola)
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno));
+ exit(2);
+ }
+ }
+
+ } else {
+ // setup the firmware flags magic number
+ const struct model *m;
+ const char *df = argv[1];
+
+ if (*df != '-')
+ usage("first argument must start with -");
+ if (*++df == '-')
+ ++df; /* allow but don't require second - */
+
+ for (m = models; ; m++) {
+ if (m->digit == '\0')
+ usage("unrecognized device specified");
+ if ((df[0] == m->digit && df[1] == '\0') || strcasecmp(df, m->name) == 0) {
+ flags = m->flags;
+ break;
+ }
+ }
+
+
+ // create a firmware image in memory
+ // and copy the trx to it
+ firmware = malloc(sizeof(struct motorola) + len);
+ memcpy(&firmware[1], trx, len);
+
+ // setup the motorola headers
+ firmware->flags = htonl(flags);
+
+ // CRC of flags + firmware
+ firmware->crc = htonl(crc32buf((unsigned char *)&firmware->flags, sizeof(firmware->flags) + len));
+
+ // write the firmware
+ if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0
+ || write(fd, firmware, sizeof(struct motorola) + len) != sizeof(struct motorola) + len
+ || close(fd) < 0)
+ {
+ fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno));
+ exit(2);
+ }
+
+ free(firmware);
+ }
+
+ munmap(trx,len);
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/myloader.h b/tools/firmware-utils/src/myloader.h
new file mode 100644
index 0000000..7be1d49
--- /dev/null
+++ b/tools/firmware-utils/src/myloader.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006-2008 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MYLOADER_H_
+#define _MYLOADER_H_
+
+/*
+ * Firmware file format:
+ *
+ * <header>
+ * [<block descriptor 0>]
+ * ...
+ * [<block descriptor n>]
+ * <null block descriptor>
+ * [<block data 0>]
+ * ...
+ * [<block data n>]
+ *
+ *
+ */
+
+/* Myloader specific magic numbers */
+#define MYLO_MAGIC_FIRMWARE 0x4C594D00
+#define MYLO_MAGIC_20021103 0x20021103
+#define MYLO_MAGIC_20021107 0x20021107
+
+#define MYLO_MAGIC_SYS_PARAMS MYLO_MAGIC_20021107
+#define MYLO_MAGIC_PARTITIONS MYLO_MAGIC_20021103
+#define MYLO_MAGIC_BOARD_PARAMS MYLO_MAGIC_20021103
+
+/*
+ * Addresses of the data structures provided by MyLoader
+ */
+#define MYLO_MIPS_SYS_PARAMS 0x80000800 /* System Parameters */
+#define MYLO_MIPS_BOARD_PARAMS 0x80000A00 /* Board Parameters */
+#define MYLO_MIPS_PARTITIONS 0x80000C00 /* Partition Table */
+#define MYLO_MIPS_BOOT_PARAMS 0x80000E00 /* Boot Parameters */
+
+/* Vendor ID's (seems to be same as the PCI vendor ID's) */
+#define VENID_COMPEX 0x11F6
+
+/* Devices based on the ADM5120 */
+#define DEVID_COMPEX_NP27G 0x0078
+#define DEVID_COMPEX_NP28G 0x044C
+#define DEVID_COMPEX_NP28GHS 0x044E
+#define DEVID_COMPEX_WP54Gv1C 0x0514
+#define DEVID_COMPEX_WP54G 0x0515
+#define DEVID_COMPEX_WP54AG 0x0546
+#define DEVID_COMPEX_WPP54AG 0x0550
+#define DEVID_COMPEX_WPP54G 0x0555
+
+/* Devices based on the Atheros AR2317 */
+#define DEVID_COMPEX_NP25G 0x05e6
+#define DEVID_COMPEX_WPE53G 0x05dc
+
+/* Devices based on the Atheros AR71xx */
+#define DEVID_COMPEX_WP543 0x0640
+#define DEVID_COMPEX_WPE72 0x0672
+
+/* Devices based on the IXP422 */
+#define DEVID_COMPEX_WP18 0x047E
+#define DEVID_COMPEX_NP18A 0x0489
+
+/* Other devices */
+#define DEVID_COMPEX_NP26G8M 0x03E8
+#define DEVID_COMPEX_NP26G16M 0x03E9
+
+struct mylo_fw_header {
+ uint32_t magic; /* must be MYLO_MAGIC_FIRMWARE */
+ uint32_t crc; /* CRC of the whole firmware */
+ uint32_t res0; /* unknown/unused */
+ uint32_t res1; /* unknown/unused */
+ uint16_t vid; /* vendor ID */
+ uint16_t did; /* device ID */
+ uint16_t svid; /* sub vendor ID */
+ uint16_t sdid; /* sub device ID */
+ uint32_t rev; /* device revision */
+ uint32_t fwhi; /* FIXME: firmware version high? */
+ uint32_t fwlo; /* FIXME: firmware version low? */
+ uint32_t flags; /* firmware flags */
+};
+
+#define FW_FLAG_BOARD_PARAMS_WP 0x01 /* board parameters are write protected */
+#define FW_FLAG_BOOT_SECTOR_WE 0x02 /* enable of write boot sectors (below 64K) */
+
+struct mylo_fw_blockdesc {
+ uint32_t type; /* block type */
+ uint32_t addr; /* relative address to flash start */
+ uint32_t dlen; /* size of block data in bytes */
+ uint32_t blen; /* total size of block in bytes */
+};
+
+#define FW_DESC_TYPE_UNUSED 0
+#define FW_DESC_TYPE_USED 1
+
+struct mylo_partition {
+ uint16_t flags; /* partition flags */
+ uint16_t type; /* type of the partition */
+ uint32_t addr; /* relative address of the partition from the
+ flash start */
+ uint32_t size; /* size of the partition in bytes */
+ uint32_t param; /* if this is the active partition, the
+ MyLoader load code to this address */
+};
+
+#define PARTITION_FLAG_ACTIVE 0x8000 /* this is the active partition,
+ * MyLoader loads firmware from here */
+#define PARTITION_FLAG_ISRAM 0x2000 /* FIXME: this is a RAM partition? */
+#define PARTIIION_FLAG_RAMLOAD 0x1000 /* FIXME: load this partition into the RAM? */
+#define PARTITION_FLAG_PRELOAD 0x0800 /* the partition data preloaded to RAM
+ * before decompression */
+#define PARTITION_FLAG_LZMA 0x0100 /* the partition data compressed with LZMA */
+#define PARTITION_FLAG_HAVEHDR 0x0002 /* the partition data have a header */
+
+#define PARTITION_TYPE_FREE 0
+#define PARTITION_TYPE_USED 1
+
+#define MYLO_MAX_PARTITIONS 8 /* maximum number of partitions in the
+ partition table */
+
+struct mylo_partition_table {
+ uint32_t magic; /* must be MYLO_MAGIC_PARTITIONS */
+ uint32_t res0; /* unknown/unused */
+ uint32_t res1; /* unknown/unused */
+ uint32_t res2; /* unknown/unused */
+ struct mylo_partition partitions[MYLO_MAX_PARTITIONS];
+};
+
+struct mylo_partition_header {
+ uint32_t len; /* length of the partition data */
+ uint32_t crc; /* CRC value of the partition data */
+};
+
+struct mylo_system_params {
+ uint32_t magic; /* must be MYLO_MAGIC_SYS_PARAMS */
+ uint32_t res0;
+ uint32_t res1;
+ uint32_t mylo_ver;
+ uint16_t vid; /* Vendor ID */
+ uint16_t did; /* Device ID */
+ uint16_t svid; /* Sub Vendor ID */
+ uint16_t sdid; /* Sub Device ID */
+ uint32_t rev; /* device revision */
+ uint32_t fwhi;
+ uint32_t fwlo;
+ uint32_t tftp_addr;
+ uint32_t prog_start;
+ uint32_t flash_size; /* Size of boot FLASH in bytes */
+ uint32_t dram_size; /* Size of onboard RAM in bytes */
+};
+
+
+struct mylo_eth_addr {
+ uint8_t mac[6];
+ uint8_t csum[2];
+};
+
+#define MYLO_ETHADDR_COUNT 8 /* maximum number of ethernet address
+ in the board parameters */
+
+struct mylo_board_params {
+ uint32_t magic; /* must be MYLO_MAGIC_BOARD_PARAMS */
+ uint32_t res0;
+ uint32_t res1;
+ uint32_t res2;
+ struct mylo_eth_addr addr[MYLO_ETHADDR_COUNT];
+};
+
+#endif /* _MYLOADER_H_*/
diff --git a/tools/firmware-utils/src/nand_ecc.c b/tools/firmware-utils/src/nand_ecc.c
new file mode 100644
index 0000000..b1e9305
--- /dev/null
+++ b/tools/firmware-utils/src/nand_ecc.c
@@ -0,0 +1,204 @@
+/*
+ * calculate ecc code for nand flash
+ *
+ * Copyright (C) 2008 yajin <yajin@vm-kernel.org>
+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#define DEF_NAND_PAGE_SIZE 2048
+#define DEF_NAND_OOB_SIZE 64
+#define DEF_NAND_ECC_OFFSET 0x28
+
+static int page_size = DEF_NAND_PAGE_SIZE;
+static int oob_size = DEF_NAND_OOB_SIZE;
+static int ecc_offset = DEF_NAND_ECC_OFFSET;
+
+/*
+ * Pre-calculated 256-way 1 byte column parity
+ */
+static const uint8_t nand_ecc_precalc_table[] = {
+ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+ 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+ 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+ 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+ 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+ 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+ 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+ 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+ 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+};
+
+/**
+ * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
+ * @dat: raw data
+ * @ecc_code: buffer for ECC
+ */
+int nand_calculate_ecc(const uint8_t *dat,
+ uint8_t *ecc_code)
+{
+ uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
+ int i;
+
+ /* Initialize variables */
+ reg1 = reg2 = reg3 = 0;
+
+ /* Build up column parity */
+ for(i = 0; i < 256; i++) {
+ /* Get CP0 - CP5 from table */
+ idx = nand_ecc_precalc_table[*dat++];
+ reg1 ^= (idx & 0x3f);
+
+ /* All bit XOR = 1 ? */
+ if (idx & 0x40) {
+ reg3 ^= (uint8_t) i;
+ reg2 ^= ~((uint8_t) i);
+ }
+ }
+
+ /* Create non-inverted ECC code from line parity */
+ tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
+ tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
+ tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
+ tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
+ tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
+ tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
+ tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
+ tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
+
+ tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
+ tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
+ tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
+ tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
+ tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
+ tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
+ tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
+ tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
+
+ /* Calculate final ECC code */
+#ifdef CONFIG_MTD_NAND_ECC_SMC
+ ecc_code[0] = ~tmp2;
+ ecc_code[1] = ~tmp1;
+#else
+ ecc_code[0] = ~tmp1;
+ ecc_code[1] = ~tmp2;
+#endif
+ ecc_code[2] = ((~reg1) << 2) | 0x03;
+
+ return 0;
+}
+
+/*
+ * usage: bb-nandflash-ecc start_address size
+ */
+void usage(const char *prog)
+{
+ fprintf(stderr, "Usage: %s [options] <input> <output>\n"
+ "Options:\n"
+ " -p <pagesize> NAND page size (default: %d)\n"
+ " -o <oobsize> NAND OOB size (default: %d)\n"
+ " -e <offset> NAND ECC offset (default: %d)\n"
+ "\n", prog, DEF_NAND_PAGE_SIZE, DEF_NAND_OOB_SIZE,
+ DEF_NAND_ECC_OFFSET);
+ exit(1);
+}
+
+/*start_address/size does not include oob
+ */
+int main(int argc, char **argv)
+{
+ uint8_t *page_data = NULL;
+ uint8_t *ecc_data;
+ int infd = -1, outfd = -1;
+ int ret = 1;
+ ssize_t bytes;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "e:o:p:")) != -1) {
+ switch(ch) {
+ case 'p':
+ page_size = strtoul(optarg, NULL, 0);
+ break;
+ case 'o':
+ oob_size = strtoul(optarg, NULL, 0);
+ break;
+ case 'e':
+ ecc_offset = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+ argc -= optind;
+ if (argc < 2)
+ usage(argv[0]);
+
+ argv += optind;
+
+ infd = open(argv[0], O_RDONLY, 0);
+ if (infd < 0) {
+ perror("open input file");
+ goto out;
+ }
+
+ outfd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (outfd < 0) {
+ perror("open output file");
+ goto out;
+ }
+
+ page_data = malloc(page_size + oob_size);
+
+ while ((bytes = read(infd, page_data, page_size)) == page_size) {
+ int j;
+
+ ecc_data = page_data + page_size + ecc_offset;
+ for (j = 0; j < page_size / 256; j++)
+ {
+ nand_calculate_ecc(page_data + j * 256, ecc_data);
+ ecc_data += 3;
+ }
+ write(outfd, page_data, page_size + oob_size);
+ }
+
+ ret = 0;
+out:
+ if (infd >= 0)
+ close(infd);
+ if (outfd >= 0)
+ close(outfd);
+ if (page_data)
+ free(page_data);
+ return ret;
+}
+
diff --git a/tools/firmware-utils/src/osbridge-crc.c b/tools/firmware-utils/src/osbridge-crc.c
new file mode 100644
index 0000000..5fd236a
--- /dev/null
+++ b/tools/firmware-utils/src/osbridge-crc.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define HOST_TO_LE16(x) (x)
+# define HOST_TO_LE32(x) (x)
+# define LE16_TO_HOST(x) (x)
+# define LE32_TO_HOST(x) (x)
+#else
+# define HOST_TO_LE16(x) bswap_16(x)
+# define HOST_TO_LE32(x) bswap_32(x)
+# define LE16_TO_HOST(x) bswap_16(x)
+# define LE32_TO_HOST(x) bswap_32(x)
+#endif
+
+uint32_t crc32buf(char *buf, size_t len);
+
+/*
+ * Globals
+ */
+static char *ifname;
+static char *progname;
+static char *ofname;
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -i <file> read input from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+ int res = EXIT_FAILURE;
+ int buflen;
+ int err;
+ struct stat st;
+ char *buf;
+ uint32_t *hdr;
+ uint32_t crc;
+
+ FILE *outfile, *infile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "i:o:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto err;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto err;
+ }
+
+ err = stat(ifname, &st);
+ if (err){
+ ERRS("stat failed on %s", ifname);
+ goto err;
+ }
+
+ buflen = st.st_size;
+ buf = malloc(buflen);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto err;
+ }
+
+ infile = fopen(ifname, "r");
+ if (infile == NULL) {
+ ERRS("could not open \"%s\" for reading", ifname);
+ goto err_free;
+ }
+
+ errno = 0;
+ fread(buf, buflen, 1, infile);
+ if (errno != 0) {
+ ERRS("unable to read from file %s", ifname);
+ goto err_close_in;
+ }
+
+ crc = crc32buf(buf, buflen);
+ hdr = (uint32_t *)buf;
+ *hdr = HOST_TO_LE32(crc);
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto err_close_in;
+ }
+
+ errno = 0;
+ fwrite(buf, buflen, 1, outfile);
+ if (errno) {
+ ERRS("unable to write to file %s", ofname);
+ goto err_close_out;
+ }
+
+ res = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(outfile);
+
+ err_close_out:
+ fclose(outfile);
+ if (res != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+
+ err_close_in:
+ fclose(infile);
+
+ err_free:
+ free(buf);
+
+ err:
+ return res;
+}
+
+/**********************************************************************/
+/* The following was grabbed and tweaked from the old snippets collection
+ * of public domain C code. */
+
+/**********************************************************************\
+|* Demonstration program to compute the 32-bit CRC used as the frame *|
+|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
+|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
+|* protocol). The 32-bit FCS was added via the Federal Register, *|
+|* 1 June 1982, p.23798. I presume but don't know for certain that *|
+|* this polynomial is or will be included in CCITT V.41, which *|
+|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
+|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
+|* errors by a factor of 10^-5 over 16-bit FCS. *|
+\**********************************************************************/
+
+/* Copyright (C) 1986 Gary S. Brown. You may use this program, or
+ code or tables extracted from it, as desired without restriction.*/
+
+/* First, the polynomial itself and its table of feedback terms. The */
+/* polynomial is */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in */
+/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
+/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
+/* the MSB being 1. */
+
+/* Note that the usual hardware shift register implementation, which */
+/* is what we're using (we're merely optimizing it by doing eight-bit */
+/* chunks at a time) shifts bits into the lowest-order term. In our */
+/* implementation, that means shifting towards the right. Why do we */
+/* do it this way? Because the calculated CRC must be transmitted in */
+/* order from highest-order term to lowest-order term. UARTs transmit */
+/* characters in order from LSB to MSB. By storing the CRC this way, */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part. Reception works similarly. */
+
+/* The feedback terms table consists of 256, 32-bit entries. Notes: */
+/* */
+/* 1. The table can be generated at runtime if desired; code to do so */
+/* is shown later. It might not be obvious, but the feedback */
+/* terms simply represent the results of eight shift/xor opera- */
+/* tions for all combinations of data and CRC register values. */
+/* */
+/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
+/* be they sixteen or thirty-two bits wide. You simply choose the */
+/* appropriate table. Alternatively, because the table can be */
+/* generated at runtime, you can start by generating the table for */
+/* the polynomial in question and use exactly the same "updcrc", */
+/* if your application needn't simultaneously handle two CRC */
+/* polynomials. (Note, however, that XMODEM is strange.) */
+/* */
+/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
+/* of course, 32-bit entries work OK if the high 16 bits are zero. */
+/* */
+/* 4. The values must be right-shifted by eight bits by the "updcrc" */
+/* logic; the shift must be unsigned (bring in zeroes). On some */
+/* hardware you could probably optimize the shift in assembler by */
+/* using byte-swap instructions. */
+
+static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
+0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
+
+uint32_t crc32buf(char *buf, size_t len)
+{
+ uint32_t crc;
+
+ crc = 0xFFFFFFFF;
+
+ for ( ; len; --len, ++buf)
+ {
+ crc = UPDC32(*buf, crc);
+ }
+
+ return crc ^ 0xFFFFFFFF;
+}
+
diff --git a/tools/firmware-utils/src/pc1crypt.c b/tools/firmware-utils/src/pc1crypt.c
new file mode 100644
index 0000000..fe41b3d
--- /dev/null
+++ b/tools/firmware-utils/src/pc1crypt.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This code was based on:
+ * PC1 Cipher Algorithm ( Pukall Cipher 1 )
+ * By Alexander PUKALL 1991
+ * free code no restriction to use
+ * please include the name of the Author in the final software
+ * the Key is 128 bits
+ * http://membres.lycos.fr/pc1/
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h> /* for unlink() */
+#include <libgen.h>
+#include <getopt.h> /* for getopt() */
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+struct pc1_ctx {
+ unsigned short ax;
+ unsigned short bx;
+ unsigned short cx;
+ unsigned short dx;
+ unsigned short si;
+ unsigned short tmp;
+ unsigned short x1a2;
+ unsigned short x1a0[8];
+ unsigned short res;
+ unsigned short i;
+ unsigned short inter;
+ unsigned short cfc;
+ unsigned short cfd;
+ unsigned short compte;
+ unsigned char cle[17];
+ short c;
+};
+
+static void pc1_finish(struct pc1_ctx *pc1)
+{
+ /* erase all variables */
+ memset(pc1, 0, sizeof(struct pc1_ctx));
+}
+
+static void pc1_code(struct pc1_ctx *pc1)
+{
+ pc1->dx = pc1->x1a2 + pc1->i;
+ pc1->ax = pc1->x1a0[pc1->i];
+ pc1->cx = 0x015a;
+ pc1->bx = 0x4e35;
+
+ pc1->tmp = pc1->ax;
+ pc1->ax = pc1->si;
+ pc1->si = pc1->tmp;
+
+ pc1->tmp = pc1->ax;
+ pc1->ax = pc1->dx;
+ pc1->dx = pc1->tmp;
+
+ if (pc1->ax != 0) {
+ pc1->ax = pc1->ax * pc1->bx;
+ }
+
+ pc1->tmp = pc1->ax;
+ pc1->ax = pc1->cx;
+ pc1->cx = pc1->tmp;
+
+ if (pc1->ax != 0) {
+ pc1->ax = pc1->ax * pc1->si;
+ pc1->cx = pc1->ax + pc1->cx;
+ }
+
+ pc1->tmp = pc1->ax;
+ pc1->ax = pc1->si;
+ pc1->si = pc1->tmp;
+ pc1->ax = pc1->ax * pc1->bx;
+ pc1->dx = pc1->cx + pc1->dx;
+
+ pc1->ax = pc1->ax + 1;
+
+ pc1->x1a2 = pc1->dx;
+ pc1->x1a0[pc1->i] = pc1->ax;
+
+ pc1->res = pc1->ax ^ pc1->dx;
+ pc1->i = pc1->i + 1;
+}
+
+static void pc1_assemble(struct pc1_ctx *pc1)
+{
+ pc1->x1a0[0] = (pc1->cle[0] * 256) + pc1->cle[1];
+
+ pc1_code(pc1);
+ pc1->inter = pc1->res;
+
+ pc1->x1a0[1] = pc1->x1a0[0] ^ ((pc1->cle[2]*256) + pc1->cle[3]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->x1a0[2] = pc1->x1a0[1] ^ ((pc1->cle[4]*256) + pc1->cle[5]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->x1a0[3] = pc1->x1a0[2] ^ ((pc1->cle[6]*256) + pc1->cle[7]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->x1a0[4] = pc1->x1a0[3] ^ ((pc1->cle[8]*256) + pc1->cle[9]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->x1a0[5] = pc1->x1a0[4] ^ ((pc1->cle[10]*256) + pc1->cle[11]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->x1a0[6] = pc1->x1a0[5] ^ ((pc1->cle[12]*256) + pc1->cle[13]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->x1a0[7] = pc1->x1a0[6] ^ ((pc1->cle[14]*256) + pc1->cle[15]);
+ pc1_code(pc1);
+ pc1->inter = pc1->inter ^ pc1->res;
+
+ pc1->i = 0;
+}
+
+static unsigned char pc1_decrypt(struct pc1_ctx *pc1, short c)
+{
+ pc1_assemble(pc1);
+ pc1->cfc = pc1->inter >> 8;
+ pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */
+
+ c = c ^ (pc1->cfc ^ pc1->cfd);
+ for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) {
+ /* we mix the plaintext byte with the key */
+ pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c;
+ }
+
+ return c;
+}
+
+static unsigned char pc1_encrypt(struct pc1_ctx *pc1, short c)
+{
+ pc1_assemble(pc1);
+ pc1->cfc = pc1->inter >> 8;
+ pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */
+
+ for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) {
+ /* we mix the plaintext byte with the key */
+ pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c;
+ }
+ c = c ^ (pc1->cfc ^ pc1->cfd);
+
+ return c;
+}
+
+static void pc1_init(struct pc1_ctx *pc1)
+{
+ memset(pc1, 0, sizeof(struct pc1_ctx));
+
+ /* ('Remsaalps!123456') is the key used, you can change it */
+ strcpy(pc1->cle, "Remsaalps!123456");
+}
+
+static void pc1_decrypt_buf(struct pc1_ctx *pc1, unsigned char *buf,
+ unsigned len)
+{
+ unsigned i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = pc1_decrypt(pc1, buf[i]);
+}
+
+static void pc1_encrypt_buf(struct pc1_ctx *pc1, unsigned char *buf,
+ unsigned len)
+{
+ unsigned i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = pc1_encrypt(pc1, buf[i]);
+}
+
+/*
+ * Globals
+ */
+static char *ifname;
+static char *progname;
+static char *ofname;
+static int decrypt;
+
+/*
+ * Message macros
+ */
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+void usage(int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ struct board_info *board;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream,
+"\n"
+"Options:\n"
+" -d decrypt instead of encrypt"
+" -i <file> read input from the file <file>\n"
+" -o <file> write output to the file <file>\n"
+" -h show this screen\n"
+ );
+
+ exit(status);
+}
+
+#define BUFSIZE (64 * 1024)
+
+int main(int argc, char *argv[])
+{
+ struct pc1_ctx pc1;
+ int res = EXIT_FAILURE;
+ int err;
+ struct stat st;
+ char *buf;
+ unsigned total;
+
+ FILE *outfile, *infile;
+
+ progname = basename(argv[0]);
+
+ while ( 1 ) {
+ int c;
+
+ c = getopt(argc, argv, "di:o:h");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'd':
+ decrypt = 1;
+ break;
+ case 'i':
+ ifname = optarg;
+ break;
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (ifname == NULL) {
+ ERR("no input file specified");
+ goto err;
+ }
+
+ if (ofname == NULL) {
+ ERR("no output file specified");
+ goto err;
+ }
+
+ err = stat(ifname, &st);
+ if (err){
+ ERRS("stat failed on %s", ifname);
+ goto err;
+ }
+
+ total = st.st_size;
+ buf = malloc(BUFSIZE);
+ if (!buf) {
+ ERR("no memory for buffer\n");
+ goto err;
+ }
+
+ infile = fopen(ifname, "r");
+ if (infile == NULL) {
+ ERRS("could not open \"%s\" for reading", ifname);
+ goto err_free;
+ }
+
+ outfile = fopen(ofname, "w");
+ if (outfile == NULL) {
+ ERRS("could not open \"%s\" for writing", ofname);
+ goto err_close_in;
+ }
+
+ pc1_init(&pc1);
+ while (total > 0) {
+ unsigned datalen;
+
+ if (total > BUFSIZE)
+ datalen = BUFSIZE;
+ else
+ datalen = total;
+
+ errno = 0;
+ fread(buf, datalen, 1, infile);
+ if (errno != 0) {
+ ERRS("unable to read from file %s", ifname);
+ goto err_close_out;
+ }
+
+ if (decrypt)
+ pc1_decrypt_buf(&pc1, buf, datalen);
+ else
+ pc1_encrypt_buf(&pc1, buf, datalen);
+
+ errno = 0;
+ fwrite(buf, datalen, 1, outfile);
+ if (errno) {
+ ERRS("unable to write to file %s", ofname);
+ goto err_close_out;
+ }
+
+ total -= datalen;
+ }
+ pc1_finish(&pc1);
+
+ res = EXIT_SUCCESS;
+
+ out_flush:
+ fflush(outfile);
+
+ err_close_out:
+ fclose(outfile);
+ if (res != EXIT_SUCCESS) {
+ unlink(ofname);
+ }
+
+ err_close_in:
+ fclose(infile);
+
+ err_free:
+ free(buf);
+
+ err:
+ return res;
+}
+
diff --git a/tools/firmware-utils/src/ptgen.c b/tools/firmware-utils/src/ptgen.c
new file mode 100644
index 0000000..2b7ec25
--- /dev/null
+++ b/tools/firmware-utils/src/ptgen.c
@@ -0,0 +1,246 @@
+/*
+ * ptgen - partition table generator
+ * Copyright (C) 2006 by Felix Fietkau <nbd@openwrt.org>
+ *
+ * uses parts of afdisk
+ * Copyright (C) 2002 by David Roetzel <david@roetzel.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 <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_le32(x) bswap_32(x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_le32(x) (x)
+#else
+#error unknown endianness!
+#endif
+
+/* Partition table entry */
+struct pte {
+ uint8_t active;
+ uint8_t chs_start[3];
+ uint8_t type;
+ uint8_t chs_end[3];
+ uint32_t start;
+ uint32_t length;
+};
+
+struct partinfo {
+ unsigned long size;
+ int type;
+};
+
+int verbose = 0;
+int active = 1;
+int heads = -1;
+int sectors = -1;
+int kb_align = 0;
+struct partinfo parts[4];
+char *filename = NULL;
+
+
+/*
+ * parse the size argument, which is either
+ * a simple number (K assumed) or
+ * K, M or G
+ *
+ * returns the size in KByte
+ */
+static long to_kbytes(const char *string) {
+ int exp = 0;
+ long result;
+ char *end;
+
+ result = strtoul(string, &end, 0);
+ switch (tolower(*end)) {
+ case 'k' :
+ case '\0' : exp = 0; break;
+ case 'm' : exp = 1; break;
+ case 'g' : exp = 2; break;
+ default: return 0;
+ }
+
+ if (*end)
+ end++;
+
+ if (*end) {
+ fprintf(stderr, "garbage after end of number\n");
+ return 0;
+ }
+
+ /* result: number + 1024^(exp) */
+ return result * ((2 << ((10 * exp) - 1)) ?: 1);
+}
+
+/* convert the sector number into a CHS value for the partition table */
+static void to_chs(long sect, unsigned char chs[3]) {
+ int c,h,s;
+
+ s = (sect % sectors) + 1;
+ sect = sect / sectors;
+ h = sect % heads;
+ sect = sect / heads;
+ c = sect;
+
+ chs[0] = h;
+ chs[1] = s | ((c >> 2) & 0xC0);
+ chs[2] = c & 0xFF;
+
+ return;
+}
+
+/* round the sector number up to the next cylinder */
+static inline unsigned long round_to_cyl(long sect) {
+ int cyl_size = heads * sectors;
+
+ return sect + cyl_size - (sect % cyl_size);
+}
+
+/* round the sector number up to the kb_align boundary */
+static inline unsigned long round_to_kb(long sect) {
+ return ((sect - 1) / kb_align + 1) * kb_align;
+}
+
+/* check the partition sizes and write the partition table */
+static int gen_ptable(uint32_t signature, int nr)
+{
+ struct pte pte[4];
+ unsigned long sect = 0;
+ int i, fd, ret = -1, start, len;
+
+ memset(pte, 0, sizeof(struct pte) * 4);
+ for (i = 0; i < nr; i++) {
+ if (!parts[i].size) {
+ fprintf(stderr, "Invalid size in partition %d!\n", i);
+ return -1;
+ }
+ pte[i].active = ((i + 1) == active) ? 0x80 : 0;
+ pte[i].type = parts[i].type;
+ start = sect + sectors;
+ if (kb_align != 0)
+ start = round_to_kb(start);
+ pte[i].start = cpu_to_le32(start);
+ sect = start + parts[i].size * 2;
+ if (kb_align == 0)
+ sect = round_to_cyl(sect);
+ pte[i].length = cpu_to_le32(len = sect - start);
+ to_chs(start, pte[i].chs_start);
+ to_chs(start + len - 1, pte[i].chs_end);
+ if (verbose)
+ fprintf(stderr, "Partition %d: start=%ld, end=%ld, size=%ld\n", i, (long) start * 512, ((long) start + (long) len) * 512, (long) len * 512);
+ printf("%ld\n", ((long) start * 512));
+ printf("%ld\n", ((long) len * 512));
+ }
+
+ if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
+ fprintf(stderr, "Can't open output file '%s'\n",filename);
+ return -1;
+ }
+
+ lseek(fd, 440, SEEK_SET);
+ if (write(fd, &signature, sizeof(signature)) != sizeof(signature)) {
+ fprintf(stderr, "write failed.\n");
+ goto fail;
+ }
+
+ lseek(fd, 446, SEEK_SET);
+ if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) {
+ fprintf(stderr, "write failed.\n");
+ goto fail;
+ }
+ lseek(fd, 510, SEEK_SET);
+ if (write(fd, "\x55\xaa", 2) != 2) {
+ fprintf(stderr, "write failed.\n");
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ close(fd);
+ return ret;
+}
+
+static void usage(char *prog)
+{
+ fprintf(stderr, "Usage: %s [-v] -h <heads> -s <sectors> -o <outputfile> [-a 0..4] [-l <align kB>] [[-t <type>] -p <size>...] \n", prog);
+ exit(1);
+}
+
+int main (int argc, char **argv)
+{
+ char type = 0x83;
+ int ch;
+ int part = 0;
+ uint32_t signature = 0x5452574F; /* 'OWRT' */
+
+ while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vl:S:")) != -1) {
+ switch (ch) {
+ case 'o':
+ filename = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'h':
+ heads = (int) strtoul(optarg, NULL, 0);
+ break;
+ case 's':
+ sectors = (int) strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ if (part > 3) {
+ fprintf(stderr, "Too many partitions\n");
+ exit(1);
+ }
+ parts[part].size = to_kbytes(optarg);
+ parts[part++].type = type;
+ break;
+ case 't':
+ type = (char) strtoul(optarg, NULL, 16);
+ break;
+ case 'a':
+ active = (int) strtoul(optarg, NULL, 0);
+ if ((active < 0) || (active > 4))
+ active = 0;
+ break;
+ case 'l':
+ kb_align = (int) strtoul(optarg, NULL, 0) * 2;
+ break;
+ case 'S':
+ signature = strtoul(optarg, NULL, 0);
+ break;
+ case '?':
+ default:
+ usage(argv[0]);
+ }
+ }
+ argc -= optind;
+ if (argc || (heads <= 0) || (sectors <= 0) || !filename)
+ usage(argv[0]);
+
+ return gen_ptable(signature, part);
+}
diff --git a/tools/firmware-utils/src/seama.c b/tools/firmware-utils/src/seama.c
new file mode 100644
index 0000000..05aee8e
--- /dev/null
+++ b/tools/firmware-utils/src/seama.c
@@ -0,0 +1,529 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2008, Alpha Networks, Inc.
+ * Created by David Hsieh <david_hsieh@alphanetworks.com>
+ * All right reserved.
+ *
+ * (SEA)ttle i(MA)ge is the image which used in project seattle.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "md5.h"
+#include "seama.h"
+
+#define PROGNAME "seama"
+#define VERSION "0.20"
+#define MAX_SEAMA_META_SIZE 1024
+#define MAX_META 128
+#define MAX_IMAGE 128
+
+extern int optind;
+extern char * optarg;
+
+static int o_verbose = 0; /* verbose mode. */
+static char * o_dump = NULL; /* Seama file to dump. */
+static char * o_seal = NULL; /* Seal the input images when file name exist. */
+static char * o_extract = NULL; /* Extract the seama file. */
+static char * o_images[MAX_IMAGE];/* The image files to pack or seal */
+static int o_isize = 0; /* number of images */
+static char * o_meta[MAX_META]; /* meta data array */
+static int o_msize = 0; /* size of meta array */
+
+static void verbose(const char * format, ...)
+{
+ va_list marker;
+ if (o_verbose)
+ {
+ va_start(marker, format);
+ vfprintf(stdout, format, marker);
+ va_end(marker);
+ }
+}
+
+static void cleanup_exit(int exit_code)
+{
+ verbose("%s: exit with code %d\n", PROGNAME, exit_code);
+ exit(exit_code);
+}
+
+static void show_usage(int exit_code)
+{
+ printf( PROGNAME " version " VERSION "\n"
+ "usage: " PROGNAME " [OPTIONS]\n"
+ " -h show this help message.\n"
+ " -v verbose mode.\n"
+ " -m {META data} META data.\n"
+ " -d {file} dump the info of the seama file.\n"
+ " -i {input file} image file name.\n"
+ " -s {file} Seal the images to the seama file.\n"
+ " -x {seama file} Extract the seama file.\n"
+ "\n"
+ " SEAMA can pack the input file (with -i) into a seama file.\n"
+ " ex: seama -i target.file\n"
+ " SEAMA can also seal multiple seama files into a single seama file.\n"
+ " ex: seama -s final.file -i taget1.seama -i target2.seama\n"
+ " To extract the raw image from SEAMA, you need to specify the meta.\n"
+ " The first image match the specified meta will be extract to\n"
+ " the output file which was specified with '-x'.\n"
+ " ex: seama -x output -i seama.image -m file=sealpac\n"
+ );
+ cleanup_exit(exit_code);
+}
+
+static int parse_args(int argc, char * argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "hvd:s:i:m:x:")) > 0)
+ {
+ switch (opt)
+ {
+ default: show_usage(-1); break;
+ case 'h': show_usage(0); break;
+ case 'v': o_verbose++; break;
+ case 'd': o_dump = optarg; break;
+ case 's': o_seal = optarg; break;
+ case 'x': o_extract = optarg; break;
+ case 'i':
+ if (o_isize < MAX_IMAGE) o_images[o_isize++] = optarg;
+ else printf("Exceed the maximum acceptable image files.!\n");
+ break;
+ case 'm':
+ if (o_msize < MAX_META) o_meta[o_msize++] = optarg;
+ else printf("Exceed the maximum acceptable META data.!\n");
+ break;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************/
+
+static size_t calculate_digest(FILE * fh, size_t size, uint8_t * digest)
+{
+ MD5_CTX ctx;
+ size_t bytes_left, bytes_read, i;
+ uint8_t buf[MAX_SEAMA_META_SIZE];
+
+ bytes_left = size ? size : sizeof(buf);
+ bytes_read = 0;
+
+ MD5_Init(&ctx);
+ while (!feof(fh) && !ferror(fh) && bytes_left > 0)
+ {
+ i = bytes_left < sizeof(buf) ? bytes_left : sizeof(buf);
+ i = fread(buf, sizeof(char), i, fh);
+ if (i > 0)
+ {
+ MD5_Update(&ctx, buf, i);
+ bytes_read += i;
+ }
+ if (size) bytes_left -= i;
+ }
+ MD5_Final(digest, &ctx);
+ return bytes_read;
+}
+
+#define READ_BUFF_SIZE 8*1024
+static size_t copy_file(FILE * to, FILE * from)
+{
+ size_t i, fsize = 0;
+ uint8_t buf[READ_BUFF_SIZE];
+
+ while (!feof(from) && !ferror(from))
+ {
+ i = fread(buf, sizeof(uint8_t), READ_BUFF_SIZE, from);
+ if (i > 0)
+ {
+ fsize += i;
+ fwrite(buf, sizeof(uint8_t), i, to);
+ }
+ }
+ return fsize;
+}
+
+static int verify_seama(const char * fname, int msg)
+{
+ FILE * fh = NULL;
+ struct stat st;
+ seamahdr_t shdr;
+ uint8_t checksum[16];
+ uint8_t digest[16];
+ uint8_t buf[MAX_SEAMA_META_SIZE];
+ size_t msize, isize, i;
+ int ret = -1;
+
+#define ERRBREAK(fmt, args...) { if (msg) printf(fmt, ##args); break; }
+
+ do
+ {
+ if (stat(fname, &st) < 0) ERRBREAK("Unable to get the info of '%s'\n",fname);
+ if ((fh = fopen(fname, "r+"))==NULL) ERRBREAK("Unable to open '%s' for reading!\n",fname);
+
+ /* Dump SEAMA header */
+ if (msg) printf("FILE - %s (%d bytes)\n", fname, (int)st.st_size);
+
+ /* SEAMA */
+ while (!feof(fh) && !ferror(fh))
+ {
+ /* read header */
+ if (fread(&shdr, sizeof(shdr), 1, fh) != 1) break;
+
+ /* Check the magic number */
+ if (shdr.magic != htonl(SEAMA_MAGIC)) ERRBREAK("Invalid SEAMA magic. Probably no more SEAMA!\n");
+
+ /* Get the size */
+ isize = ntohl(shdr.size);
+ msize = ntohs(shdr.metasize);
+
+ /* The checksum exist only if size is greater than zero. */
+ if (isize > 0)
+ {
+ if (fread(checksum, sizeof(checksum), 1, fh) != 1)
+ ERRBREAK("Error reading checksum !\n");
+ }
+
+ /* Check the META size. */
+ if (msize > sizeof(buf)) ERRBREAK("META data in SEAMA header is too large!\n");
+
+ /* Read META data. */
+ if (fread(buf, sizeof(char), msize, fh) != msize)
+ ERRBREAK("Unable to read SEAMA META data!\n");
+
+ /* dump header */
+ if (msg)
+ {
+ printf("SEAMA ==========================================\n");
+ printf(" magic : %08x\n", ntohl(shdr.magic));
+ printf(" meta size : %zu bytes\n", msize);
+ for (i=0; i<msize; i+=(strlen((const char *)&buf[i])+1))
+ printf(" meta data : %s\n", &buf[i]);
+ printf(" image size : %zu bytes\n", isize);
+ }
+
+ /* verify checksum */
+ if (isize > 0)
+ {
+ if (msg)
+ {
+ printf(" checksum : ");
+ for (i=0; i<16; i++) printf("%02X", checksum[i]);
+ printf("\n");
+ }
+
+ /* Calculate the checksum */
+ calculate_digest(fh, isize, digest);
+ if (msg)
+ {
+ printf(" digest : ");
+ for (i=0; i<16; i++) printf("%02X", digest[i]);
+ printf("\n");
+ }
+
+ if (memcmp(checksum, digest, 16)!=0) ERRBREAK("!!ERROR!! checksum error !!\n");
+ ret = 0;
+ }
+ }
+ if (msg) printf("================================================\n");
+ } while (0);
+ if (fh) fclose(fh);
+ return ret;
+}
+
+static size_t write_seama_header(FILE * fh, char * meta[], size_t msize, size_t size)
+{
+ seamahdr_t shdr;
+ size_t i;
+ uint16_t metasize = 0;
+
+ /* Calculate the META size */
+ for (i=0; i<msize; i++) metasize += (strlen(meta[i]) + 1);
+ //+++ let meta data end on 4 alignment by siyou. 2010/3/1 03:58pm
+ metasize = ((metasize+3)/4)*4;
+ verbose("SEAMA META : %d bytes\n", metasize);
+
+ /* Fill up the header, all the data endian should be network byte order. */
+ shdr.magic = htonl(SEAMA_MAGIC);
+ shdr.reserved = 0;
+ shdr.metasize = htons(metasize);
+ shdr.size = htonl(size);
+
+ /* Write the header */
+ return fwrite(&shdr, sizeof(seamahdr_t), 1, fh);
+}
+
+static size_t write_checksum(FILE * fh, uint8_t * checksum)
+{
+ return fwrite(checksum, sizeof(uint8_t), 16, fh);
+}
+
+static size_t write_meta_data(FILE * fh, char * meta[], size_t size)
+{
+ size_t i,j;
+ size_t ret = 0;
+
+ for (i=0; i<size; i++)
+ {
+ verbose("SEAMA META data : %s\n", meta[i]);
+ j = fwrite(meta[i], sizeof(char), strlen(meta[i])+1, fh);
+ if (j != strlen(meta[i])+1) return 0;
+ ret += j;
+ }
+ //+++ let meta data end on 4 alignment by siyou. 2010/3/1 03:58pm
+ j = ((ret+3)/4)*4;
+ for ( ; ret < j; ret++)
+ fwrite("", sizeof(char), 1, fh);
+
+ return ret;
+}
+
+/*******************************************************************/
+
+static void dump_seama(const char * fname)
+{
+ verify_seama(fname, 1);
+}
+
+static void seal_files(const char * file)
+{
+ FILE * fh;
+ FILE * ifh;
+ size_t i;
+
+ /* Each image should be seama. */
+ for (i = 0; i < o_isize; i++)
+ {
+ if (verify_seama(o_images[i], 0) < 0)
+ {
+ printf("'%s' is not a seama file !\n",o_images[i]);
+ return;
+ }
+ }
+
+ /* Open file for write */
+ fh = fopen(file, "w+");
+ if (fh)
+ {
+ /* Write the header. */
+ write_seama_header(fh, o_meta, o_msize, 0);
+ write_meta_data(fh, o_meta, o_msize);
+
+ /* Write image files */
+ for (i=0; i<o_isize; i++)
+ {
+ ifh = fopen(o_images[i], "r+");
+ if (ifh)
+ {
+ copy_file(fh, ifh);
+ fclose(ifh);
+ }
+ }
+
+ fclose(fh);
+ }
+}
+
+static void pack_files(void)
+{
+ FILE * fh;
+ FILE * ifh;
+ size_t i, fsize;
+ char filename[512];
+ uint8_t digest[16];
+
+ for (i=0; i<o_isize; i++)
+ {
+ /* Open the input file. */
+ ifh = fopen(o_images[i], "r+");
+ if (ifh)
+ {
+ fsize = calculate_digest(ifh, 0, digest);
+ verbose("file size (%s) : %d\n", o_images[i], fsize);
+ rewind(ifh);
+
+ /* Open the output file. */
+ sprintf(filename, "%s.seama", o_images[i]);
+ fh = fopen(filename, "w+");
+ if (fh)
+ {
+ write_seama_header(fh, o_meta, o_msize, fsize);
+ write_checksum(fh, digest);
+ write_meta_data(fh, o_meta, o_msize);
+ copy_file(fh, ifh);
+ fclose(fh);
+ }
+ fclose(ifh);
+ }
+ else
+ {
+ printf("Unable to open image file '%s'\n",o_images[i]);
+ }
+ }
+}
+
+/**************************************************************************/
+
+static int match_meta(const char * meta, size_t size)
+{
+ size_t i, j;
+ int match;
+
+ for (i = 0; i < o_msize; i++)
+ {
+ for (match = 0, j = 0; j < size; j += (strlen(&meta[j])+1))
+ if (strcmp(&meta[j], o_meta[i])==0) { match++; break; }
+ if (!match) return 0;
+ }
+ return 1;
+}
+
+
+static void extract_file(const char * output)
+{
+ FILE * ifh = NULL;
+ FILE * ofh = NULL;
+ size_t msize, isize, i, m;
+ seamahdr_t shdr;
+ uint8_t buf[MAX_SEAMA_META_SIZE];
+ int done = 0;
+
+ /* We need meta for searching the target image. */
+ if (o_msize == 0)
+ {
+ printf("SEAMA: need meta for searching image.\n");
+ return;
+ }
+
+ /* Walk through each input file */
+ for (i = 0; i < o_isize; i++)
+ {
+ /* verify the input file */
+ if (verify_seama(o_images[i], 0) < 0)
+ {
+ printf("SEAMA: '%s' is not a seama file !\n", o_images[i]);
+ continue;
+ }
+ /* open the input file */
+ ifh = fopen(o_images[i], "r");
+ if (!ifh) continue;
+ /* read file */
+ while (!feof(ifh) && !ferror(ifh))
+ {
+ /* read header */
+ fread(&shdr, sizeof(shdr), 1, ifh);
+ if (shdr.magic != htonl(SEAMA_MAGIC)) break;
+ /* Get the size */
+ isize = ntohl(shdr.size);
+ msize = ntohs(shdr.metasize);
+ if (isize == 0)
+ {
+ while (msize > 0)
+ {
+ m = fread(buf, sizeof(char), (msize < MAX_SEAMA_META_SIZE) ? msize : MAX_SEAMA_META_SIZE, ifh);
+ if (m <= 0) break;
+ msize -= m;
+ }
+ continue;
+ }
+ /* read checksum */
+ fread(buf, sizeof(char), 16, ifh);
+ if (msize > 0)
+ {
+ /* read META */
+ fread(buf, sizeof(char), msize, ifh);
+ if (match_meta((const char *)buf, msize))
+ {
+ printf("SEAMA: found image @ '%s', image size: %zu\n", o_images[i], isize);
+ /* open output file */
+ ofh = fopen(output, "w");
+ if (!ofh) printf("SEAMA: unable to open '%s' for writting.\n",output);
+ else
+ {
+ while (isize > 0)
+ {
+ m = fread(buf, sizeof(char), (isize < MAX_SEAMA_META_SIZE) ? isize : MAX_SEAMA_META_SIZE, ifh);
+ if (m <= 0) break;
+ fwrite(buf, sizeof(char), m, ofh);
+ isize -= m;
+ }
+ fclose(ofh);
+ }
+ done++;
+ break;
+ }
+ }
+ while (isize > 0)
+ {
+ m = fread(buf, sizeof(char), (isize < MAX_SEAMA_META_SIZE) ? isize : MAX_SEAMA_META_SIZE, ifh);
+ if (m <= 0) break;
+ isize -= m;
+ }
+ }
+ /* close the file. */
+ fclose(ifh);
+ if (done) break;
+ }
+ return;
+}
+
+/*******************************************************************/
+#ifdef RGBIN_BOX
+int seama_main(int argc, char * argv[], char * env[])
+#else
+int main(int argc, char * argv[], char * env[])
+#endif
+{
+ verbose("SEAMA version " VERSION "\n");
+
+ /* parse the arguments */
+ if (parse_args(argc, argv) < 0) show_usage(9);
+
+ /* Do the works */
+ if (o_dump) dump_seama(o_dump);
+ else if (o_seal) seal_files(o_seal);
+ else if (o_extract) extract_file(o_extract);
+ else pack_files();
+
+ cleanup_exit(0);
+ return 0;
+}
diff --git a/tools/firmware-utils/src/seama.h b/tools/firmware-utils/src/seama.h
new file mode 100644
index 0000000..02683b6
--- /dev/null
+++ b/tools/firmware-utils/src/seama.h
@@ -0,0 +1,108 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * (SEA)ttle i(MA)ge is the image which used in project seattle.
+ *
+ * Created by David Hsieh <david_hsieh@alphanetworks.com>
+ * Copyright (C) 2008-2009 Alpha Networks, Inc.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either'
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ */
+
+#ifndef __SEAMA_HEADER_FILE__
+#define __SEAMA_HEADER_FILE__
+
+#include <stdint.h>
+
+#define SEAMA_MAGIC 0x5EA3A417
+
+/*
+ * SEAMA looks like the following map.
+ * All the data of the header should be in network byte order.
+ *
+ * +-------------+-------------+------------
+ * | SEAMA magic | ^
+ * +-------------+-------------+ |
+ * | reserved | meta size | |
+ * +-------------+-------------+ header
+ * | image size (0 bytes) | |
+ * +-------------+-------------+ |
+ * ~ Meta data ~ v
+ * +-------------+-------------+------------
+ * | SEAMA magic | ^ ^
+ * +-------------+-------------+ | |
+ * | reserved | meta size | | |
+ * +-------------+-------------+ | |
+ * | image size | | |
+ * +-------------+-------------+ header |
+ * | | | |
+ * | 16 bytes of MD5 digest | | |
+ * | | | |
+ * | | | |
+ * +-------------+-------------+ | |
+ * ~ Meta data ~ v |
+ * +-------------+-------------+------- |
+ * | | |
+ * | Image of the 1st entity | |
+ * ~ ~ 1st entity
+ * | | |
+ * | | v
+ * +-------------+-------------+-------------
+ * | SEAMA magic | ^ ^
+ * +-------------+-------------+ | |
+ * | reserved | meta size | | |
+ * +-------------+-------------+ | |
+ * | image size | | |
+ * +-------------+-------------+ header |
+ * | | | |
+ * | 16 bytes of MD5 digest | | |
+ * | | | |
+ * | | | |
+ * +-------------+-------------+ | |
+ * ~ Meta data ~ v |
+ * +-------------+-------------+------- |
+ * | | |
+ * | Image of the 2nd entity | |
+ * ~ ~ 2nd entity
+ * | | |
+ * | | v
+ * +-------------+-------------+-------------
+ */
+
+
+/*
+ * SEAMA header
+ *
+ * |<-------- 32 bits -------->|
+ * +-------------+-------------+
+ * | SEAMA magic |
+ * +-------------+-------------+
+ * | reserved | meta size |
+ * +-------------+-------------+
+ * | image size |
+ * +-------------+-------------+
+ */
+/* seama header */
+typedef struct seama_hdr seamahdr_t;
+struct seama_hdr
+{
+ uint32_t magic; /* should always be SEAMA_MAGIC. */
+ uint16_t reserved; /* reserved for */
+ uint16_t metasize; /* size of the META data */
+ uint32_t size; /* size of the image */
+} __attribute__ ((packed));
+
+
+#endif
diff --git a/tools/firmware-utils/src/sha1.c b/tools/firmware-utils/src/sha1.c
new file mode 100644
index 0000000..3ab1332
--- /dev/null
+++ b/tools/firmware-utils/src/sha1.c
@@ -0,0 +1,443 @@
+/*
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Copyright (C) 2003-2006 Christophe Devine
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License, version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+/*
+ * The SHA-1 standard was published by NIST in 1993.
+ *
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "sha1.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (ulong) (b)[(i) ] << 24 ) \
+ | ( (ulong) (b)[(i) + 1] << 16 ) \
+ | ( (ulong) (b)[(i) + 2] << 8 ) \
+ | ( (ulong) (b)[(i) + 3] ); \
+}
+#endif
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (uchar) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (uchar) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (uchar) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (uchar) ( (n) ); \
+}
+#endif
+
+/*
+ * Core SHA-1 functions
+ */
+void sha1_starts( sha1_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+void sha1_process( sha1_context *ctx, uchar data[64] )
+{
+ ulong temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE( W[0], data, 0 );
+ GET_UINT32_BE( W[1], data, 4 );
+ GET_UINT32_BE( W[2], data, 8 );
+ GET_UINT32_BE( W[3], data, 12 );
+ GET_UINT32_BE( W[4], data, 16 );
+ GET_UINT32_BE( W[5], data, 20 );
+ GET_UINT32_BE( W[6], data, 24 );
+ GET_UINT32_BE( W[7], data, 28 );
+ GET_UINT32_BE( W[8], data, 32 );
+ GET_UINT32_BE( W[9], data, 36 );
+ GET_UINT32_BE( W[10], data, 40 );
+ GET_UINT32_BE( W[11], data, 44 );
+ GET_UINT32_BE( W[12], data, 48 );
+ GET_UINT32_BE( W[13], data, 52 );
+ GET_UINT32_BE( W[14], data, 56 );
+ GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
+ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+void sha1_update( sha1_context *ctx, uchar *input, uint length )
+{
+ ulong left, fill;
+
+ if( ! length ) return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < length )
+ ctx->total[1]++;
+
+ if( left && length >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ sha1_process( ctx, ctx->buffer );
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while( length >= 64 )
+ {
+ sha1_process( ctx, input );
+ length -= 64;
+ input += 64;
+ }
+
+ if( length )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, length );
+ }
+}
+
+static uchar sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void sha1_finish( sha1_context *ctx, uchar digest[20] )
+{
+ ulong last, padn;
+ ulong high, low;
+ uchar msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha1_update( ctx, sha1_padding, padn );
+ sha1_update( ctx, msglen, 8 );
+
+ PUT_UINT32_BE( ctx->state[0], digest, 0 );
+ PUT_UINT32_BE( ctx->state[1], digest, 4 );
+ PUT_UINT32_BE( ctx->state[2], digest, 8 );
+ PUT_UINT32_BE( ctx->state[3], digest, 12 );
+ PUT_UINT32_BE( ctx->state[4], digest, 16 );
+}
+
+/*
+ * Output SHA-1(file contents), returns 0 if successful.
+ */
+int sha1_file( char *filename, uchar digest[20] )
+{
+ FILE *f;
+ size_t n;
+ sha1_context ctx;
+ uchar buf[1024];
+
+ if( ( f = fopen( filename, "rb" ) ) == NULL )
+ return( 1 );
+
+ sha1_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha1_update( &ctx, buf, (uint) n );
+
+ sha1_finish( &ctx, digest );
+
+ fclose( f );
+ return( 0 );
+}
+
+/*
+ * Output SHA-1(buf)
+ */
+void sha1_csum( uchar *buf, uint buflen, uchar digest[20] )
+{
+ sha1_context ctx;
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, buf, buflen );
+ sha1_finish( &ctx, digest );
+}
+
+/*
+ * Output HMAC-SHA-1(key,buf)
+ */
+void sha1_hmac( uchar *key, uint keylen, uchar *buf, uint buflen,
+ uchar digest[20] )
+{
+ uint i;
+ sha1_context ctx;
+ uchar k_ipad[64];
+ uchar k_opad[64];
+ uchar tmpbuf[20];
+
+ memset( k_ipad, 0x36, 64 );
+ memset( k_opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ if( i >= 64 ) break;
+
+ k_ipad[i] ^= key[i];
+ k_opad[i] ^= key[i];
+ }
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, k_ipad, 64 );
+ sha1_update( &ctx, buf, buflen );
+ sha1_finish( &ctx, tmpbuf );
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, k_opad, 64 );
+ sha1_update( &ctx, tmpbuf, 20 );
+ sha1_finish( &ctx, digest );
+
+ memset( k_ipad, 0, 64 );
+ memset( k_opad, 0, 64 );
+ memset( tmpbuf, 0, 20 );
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#ifdef SELF_TEST
+/*
+ * FIPS-180-1 test vectors
+ */
+static char *sha1_test_str[3] =
+{
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ NULL
+};
+
+static uchar sha1_test_sum[3][20] =
+{
+ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+ { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+ 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( void )
+{
+ int i, j;
+ uchar buf[1000];
+ uchar sha1sum[20];
+ sha1_context ctx;
+
+ for( i = 0; i < 3; i++ )
+ {
+ printf( " SHA-1 test #%d: ", i + 1 );
+
+ sha1_starts( &ctx );
+
+ if( i < 2 )
+ sha1_update( &ctx, (uchar *) sha1_test_str[i],
+ strlen( sha1_test_str[i] ) );
+ else
+ {
+ memset( buf, 'a', 1000 );
+ for( j = 0; j < 1000; j++ )
+ sha1_update( &ctx, (uchar *) buf, 1000 );
+ }
+
+ sha1_finish( &ctx, sha1sum );
+
+ if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+ {
+ printf( "failed\n" );
+ return( 1 );
+ }
+
+ printf( "passed\n" );
+ }
+
+ printf( "\n" );
+ return( 0 );
+}
+#else
+int sha1_self_test( void )
+{
+ printf( "SHA-1 self-test not available\n\n" );
+ return( 1 );
+}
+#endif
diff --git a/tools/firmware-utils/src/sha1.h b/tools/firmware-utils/src/sha1.h
new file mode 100644
index 0000000..425267a
--- /dev/null
+++ b/tools/firmware-utils/src/sha1.h
@@ -0,0 +1,57 @@
+#ifndef _SHA1_H
+#define _SHA1_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _STD_TYPES
+#define _STD_TYPES
+
+#define uchar unsigned char
+#define uint unsigned int
+#define ulong unsigned long int
+
+#endif
+
+typedef struct
+{
+ ulong total[2];
+ ulong state[5];
+ uchar buffer[64];
+}
+sha1_context;
+
+/*
+ * Core SHA-1 functions
+ */
+void sha1_starts( sha1_context *ctx );
+void sha1_update( sha1_context *ctx, uchar *input, uint length );
+void sha1_finish( sha1_context *ctx, uchar digest[20] );
+
+/*
+ * Output SHA-1(file contents), returns 0 if successful.
+ */
+int sha1_file( char *filename, uchar digest[20] );
+
+/*
+ * Output SHA-1(buf)
+ */
+void sha1_csum( uchar *buf, uint buflen, uchar digest[20] );
+
+/*
+ * Output HMAC-SHA-1(key,buf)
+ */
+void sha1_hmac( uchar *key, uint keylen, uchar *buf, uint buflen,
+ uchar digest[20] );
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */
diff --git a/tools/firmware-utils/src/spw303v.c b/tools/firmware-utils/src/spw303v.c
new file mode 100644
index 0000000..ae34a1e
--- /dev/null
+++ b/tools/firmware-utils/src/spw303v.c
@@ -0,0 +1,242 @@
+/*
+ * spw303v.c - partially based on OpenWrt's imagetag.c and addpattern.c
+ *
+ * Copyright (C) 2011 Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#define IMAGE_LEN 10 /* Length of Length Field */
+#define ADDRESS_LEN 12 /* Length of Address field */
+#define TAGID_LEN 6 /* Length of tag ID */
+#define TAGINFO_LEN 20 /* Length of vendor information field in tag */
+#define TAGVER_LEN 4 /* Length of Tag Version */
+#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
+
+
+struct spw303v_tag
+{
+ unsigned char tagVersion[4]; // tag version. Will be 2 here.
+ unsigned char signiture_1[20]; // text line for company info
+ unsigned char signiture_2[14]; // additional info (can be version number)
+ unsigned char chipId[6]; // chip id
+ unsigned char boardId[16]; // board id
+ unsigned char bigEndian[2]; // if = 1 - big, = 0 - little endia of the host
+ unsigned char totalImageLen[IMAGE_LEN]; // the sum of all the following length
+ unsigned char cfeAddress[ADDRESS_LEN]; // if non zero, cfe starting address
+ unsigned char cfeLen[IMAGE_LEN]; // if non zero, cfe size in clear ASCII text.
+ unsigned char rootfsAddress[ADDRESS_LEN]; // if non zero, filesystem starting address
+ unsigned char rootfsLen[IMAGE_LEN]; // if non zero, filesystem size in clear ASCII text.
+ unsigned char kernelAddress[ADDRESS_LEN]; // if non zero, kernel starting address
+ unsigned char kernelLen[IMAGE_LEN]; // if non zero, kernel size in clear ASCII text.
+
+ unsigned char certf1Address[ADDRESS_LEN];
+ unsigned char certf1Len[6];
+ unsigned char certf2Address[ADDRESS_LEN];
+ unsigned char certf2Len[6];
+ unsigned char certf3Address[ADDRESS_LEN];
+ unsigned char certf3Len[6];
+ unsigned char httpsFileSize[4];
+ unsigned char tr64FileSize[4];
+ unsigned char tr69FileSize[4];
+ unsigned char filesmap[4];
+
+ unsigned char imageSequence[4]; // incrments everytime an image is flashed
+ unsigned char reserved[4]; // reserved for later use
+ unsigned char imageCRC[4]; // 216-219: CRC32 of images
+ unsigned char reserved2[16]; // 220-235: Unused at present
+ unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion
+ unsigned char reserved3[16]; // 240-255: Unused at present
+};
+
+static uint32_t crc32tab[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+#define IMAGETAG_CRC_START 0xFFFFFFFF
+
+#define IMAGETAG_MAGIC1_TCOM "AAAAAAAA Corporatio"
+
+static char fake_data[] = {
+ 0x18, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 ,0x18,
+ 0x21, 0x24, 0x21, 0x1b, 0x18, 0x18, 0x24, 0x24, 0x18, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x1b, 0x18, 0x18, 0x24, 0x24, 0x21, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18,
+ 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21,
+ 0x21, 0x21, 0x21, 0x21,
+};
+
+
+uint32_t crc32(uint32_t crc, uint8_t *data, size_t len)
+{
+ while (len--)
+ crc = (crc >> 8) ^ crc32tab[(crc ^ *data++) & 0xFF];
+
+ return crc;
+}
+
+void fix_header(void *buf)
+{
+ struct spw303v_tag *tag = buf;
+ uint32_t crc;
+ /* Replace signature with custom t-com one */
+ memset(tag->signiture_1, 0, 20);
+ memcpy(tag->signiture_1, IMAGETAG_MAGIC1_TCOM, strlen(IMAGETAG_MAGIC1_TCOM));
+
+ /* Clear cert fields to remove information_* data */
+ memset(tag->certf1Address, 0, 74);
+
+ /* replace image crc with modified one */
+ crc = ntohl(*((uint32_t *)&tag->imageCRC));
+
+ crc = htonl(crc32(crc, fake_data, 64));
+
+ memcpy(tag->imageCRC, &crc, 4);
+
+ /* Update tag crc */
+ crc = htonl(crc32(IMAGETAG_CRC_START, buf, 236));
+ memcpy(tag->headerCRC, &crc, 4);
+}
+
+
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: spw303v [-i <inputfile>] [-o <outputfile>]\n");
+ exit(EXIT_FAILURE);
+}
+
+
+int main(int argc, char **argv)
+{
+ char buf[1024]; /* keep this at 1k or adjust garbage calc below */
+ FILE *in = stdin;
+ FILE *out = stdout;
+ char *ifn = NULL;
+ char *ofn = NULL;
+ int c;
+ int v0, v1, v2;
+ size_t n;
+ int first_block = 1;
+
+ uint32_t image_crc = IMAGETAG_CRC_START;
+
+ while ((c = getopt(argc, argv, "i:o:h")) != -1) {
+ switch (c) {
+ case 'i':
+ ifn = optarg;
+ break;
+ case 'o':
+ ofn = optarg;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc || optind == 1) {
+ fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
+ usage();
+ }
+
+ if (ifn && !(in = fopen(ifn, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
+ usage();
+ }
+
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+
+
+ while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
+ if (n < sizeof(buf)) {
+ if (ferror(in)) {
+ FREAD_ERROR:
+ fprintf(stderr, "fread error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (first_block && n >= 256) {
+ fix_header(buf);
+ first_block = 0;
+ }
+
+ image_crc = crc32(image_crc, buf, n);
+
+ if (!fwrite(buf, n, 1, out)) {
+ FWRITE_ERROR:
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (ferror(in)) {
+ goto FREAD_ERROR;
+ }
+
+ if (fflush(out)) {
+ goto FWRITE_ERROR;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/srec2bin.c b/tools/firmware-utils/src/srec2bin.c
new file mode 100644
index 0000000..1cffbae
--- /dev/null
+++ b/tools/firmware-utils/src/srec2bin.c
@@ -0,0 +1,524 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+//Rev 0.1 Original
+// 8 Jan 2001 MJH Added code to write data to Binary file
+// note: outputfile is name.bin, where name is first part
+// of input file. ie tmp.rec -> tmp.bin
+//
+// srec2bin <input SREC file> <Output Binary File> <If Present, Big Endian>
+//
+// TAG
+// bit32u TAG_BIG = 0xDEADBE42;
+// bit32u TAG_LITTLE = 0xFEEDFA42;
+//
+// File Structure
+//
+// TAG : 32 Bits
+// [DATA RECORDS]
+//
+// Data Records Structure
+//
+// LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM
+// ADDRESS : 32 Bits
+// DATA : 8 Bits * LENGTH
+// CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data)
+//
+// Note : If Length == 0, Address will be Program Start
+//
+//
+//
+//
+//
+
+#define MajRevNum 0
+#define MinRevNum 2
+
+
+#define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) )
+
+typedef unsigned char bit8u;
+typedef unsigned int bit32u;
+typedef int bit32;
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+
+bit32u CheckSum;
+int RecStart;
+int debug;
+int verbose;
+
+FILE *OpenOutputFile( char *Name );
+FILE *fOut;
+bit32u RecLength=0;
+
+bit32u AddressCurrent;
+
+bit32u gh(char *cp,int nibs);
+
+int BigEndian;
+
+int inputline;
+
+// char buf[16*1024];
+
+char buffer[2048];
+char *cur_ptr;
+int cur_line=0;
+int cur_len=0;
+
+int s1s2s3_total=0;
+
+bit32u PBVal;
+int PBValid;
+bit32u PBAdr;
+
+
+void dumpfTell(char *s, bit32u Value)
+{
+ int Length;
+ Length = (int) RecLength;
+ if (debug)
+ printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n",
+ s, ftell(fOut), Length, Length, Value);
+}
+
+void DispHex(bit32u Hex)
+{
+// printf("%X", Hex);
+}
+
+void WaitDisplay(void)
+{
+ static int Count=0;
+ static int Index=0;
+ char iline[]={"-\\|/"};
+
+ Count++;
+ if ((Count % 32)==0)
+ {
+ if (verbose)
+ printf("%c%c",iline[Index++],8);
+ Index &= 3;
+ }
+}
+
+
+void binOut32 ( bit32u Data )
+{
+// On UNIX machine all 32bit writes need ENDIAN switched
+// Data = EndianSwitch(Data);
+// fwrite( &Data, sizeof(bit32u), 1, fOut);
+
+ char sdat[4];
+ int i;
+
+ for(i=0;i<4;i++)
+ sdat[i]=(char)(Data>>(i*8));
+ fwrite( sdat, 1, 4, fOut);
+ dumpfTell("Out32" , Data);
+}
+
+// Only update RecLength on Byte Writes
+// All 32 bit writes will be for Length etc
+
+void binOut8 ( bit8u Data )
+{
+ int n;
+ dumpfTell("B4Data" , (bit32u) (Data & 0xFF) );
+ n = fwrite( &Data, sizeof(bit8u), 1, fOut);
+ if (n != 1)
+ printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent);
+ RecLength += 1;
+}
+
+// Currently ONLY used for outputting Program Start
+
+void binRecStart(bit32u Address)
+{
+ RecLength = 0;
+ CheckSum = Address;
+ RecStart = TRUE;
+
+ if (debug)
+ printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n",
+ CheckSum, RecLength, Address);
+
+
+ dumpfTell("RecLength", RecLength);
+ binOut32( RecLength );
+ dumpfTell("Address", Address);
+ binOut32( Address );
+}
+
+void binRecEnd(void)
+{
+ long RecEnd;
+
+ if (!RecStart) // if no record started, do not end it
+ {
+ return;
+ }
+
+ RecStart = FALSE;
+
+
+ RecEnd = ftell(fOut); // Save Current position
+
+ if (debug)
+ printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n",
+ CheckSum, RecLength, RecLength, RecEnd);
+
+ fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data
+
+ dumpfTell("Data ", -1);
+
+ fseek( fOut, -4, SEEK_CUR); // move back Start Of Address
+
+ dumpfTell("Address ", -1);
+
+ fseek( fOut, -4, SEEK_CUR); // move back Start Of Length
+
+ dumpfTell("Length ", -1);
+
+ binOut32( RecLength );
+
+ fseek( fOut, RecEnd, SEEK_SET); // move to end of Record
+
+ CheckSum += RecLength;
+
+ CheckSum = ~CheckSum + 1; // Two's complement
+
+ binOut32( CheckSum );
+
+ if (verbose)
+ printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum);
+}
+
+void binRecOutProgramStart(bit32u Address)
+{
+ if (Address != (AddressCurrent+1))
+ {
+ binRecEnd();
+ binRecStart(Address);
+ }
+ AddressCurrent = Address;
+}
+void binRecOutByte(bit32u Address, bit8u Data)
+{
+ // If Address is one after Current Address, output Byte
+ // If not, close out last record, update Length, write checksum
+ // Then Start New Record, updating Current Address
+
+ if (Address != (AddressCurrent+1))
+ {
+ binRecEnd();
+ binRecStart(Address);
+ }
+ AddressCurrent = Address;
+ CheckSum += Data;
+ binOut8( Data );
+}
+
+//=============================================================================
+// SUPPORT FUNCTIONS
+//=============================================================================
+int readline(FILE *fil,char *buf,int len)
+{
+ int rlen;
+
+ rlen=0;
+ if (len==0) return(0);
+ while(1)
+ {
+ if (cur_len==0)
+ {
+ cur_len=fread(buffer, 1, sizeof(buffer), fil);
+ if (cur_len==0)
+ {
+ if (rlen)
+ {
+ *buf=0;
+ return(rlen);
+ }
+ return(-1);
+ }
+ cur_ptr=buffer;
+ }
+ if (cur_len)
+ {
+ if (*cur_ptr=='\n')
+ {
+ *buf=0;
+ cur_ptr++;
+ cur_len--;
+ return(rlen);
+ }
+ else
+ {
+ if ((len>1)&&(*cur_ptr!='\r'))
+ {
+ *buf++=*cur_ptr++;
+ len--;
+ }
+ else
+ cur_ptr++;
+
+ rlen++;
+ cur_len--;
+ }
+ }
+ else
+ {
+ *buf=0;
+ cur_ptr++;
+ cur_len--;
+ return(rlen);
+ }
+ }
+}
+
+
+int SRLerrorout(char *c1,char *c2)
+{
+ printf("\nERROR: %s - '%s'.",c1,c2);
+ return(FALSE);
+}
+
+
+int checksum(char *cp,int count)
+{
+ char *scp;
+ int cksum;
+ int dum;
+
+ scp=cp;
+ while(*scp)
+ {
+ if (!isxdigit(*scp++))
+ return(SRLerrorout("Invalid hex digits",cp));
+ }
+ scp=cp;
+
+ cksum=count;
+
+ while(count)
+ {
+ cksum += gh(scp,2);
+ if (count == 2)
+ dum = ~cksum;
+ scp += 2;
+ count--;
+ }
+ cksum&=0x0ff;
+ // printf("\nCk:%02x",cksum);
+ return(cksum==0x0ff);
+}
+
+bit32u gh(char *cp,int nibs)
+{
+ int i;
+ bit32u j;
+
+ j=0;
+
+ for(i=0;i<nibs;i++)
+ {
+ j<<=4;
+ if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f;
+ if ((*cp>='0')&&(*cp<='9'))
+ j += (*cp-0x30);
+ else
+ if ((*cp>='A')&&(*cp<='F'))
+ j += (*cp-0x37);
+ else
+ SRLerrorout("Bad Hex char", cp);
+ cp++;
+ }
+ return(j);
+}
+
+
+//=============================================================================
+// PROCESS SREC LINE
+//=============================================================================
+
+int srecLine(char *pSrecLine)
+{
+ char *scp,ch;
+ int itmp,count,dat;
+ bit32u adr;
+ static bit32u RecordCounter=0;
+
+ cur_line++;
+ scp=pSrecLine;
+
+ if (*pSrecLine!='S')
+ return(SRLerrorout("Not an Srecord file",scp));
+ pSrecLine++;
+ if (strlen(pSrecLine)<4)
+ return(SRLerrorout("Srecord too short",scp));
+
+ ch=*pSrecLine++;
+
+ count=gh(pSrecLine,2);
+
+ pSrecLine += 2;
+
+ // if(debug)
+ // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine);
+ RecordCounter++;
+ DispHex(RecordCounter);
+
+ if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp));
+
+ if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp));
+
+ switch(ch)
+ {
+ case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
+ if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp));
+ break;
+ case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
+ adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
+ count--;
+ while(count)
+ {
+ dat=gh(pSrecLine,2); pSrecLine+=2; count--;
+ binRecOutByte(adr, (char) (dat & 0xFF));
+ adr++;
+ }
+ s1s2s3_total++;
+ break;
+ case '4': return(SRLerrorout("Invalid Srecord type",scp));
+ break;
+ case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
+ if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp));
+ break;
+ case '6': return(SRLerrorout("Invalid Srecord type",scp));
+ break;
+ case '7': // PROGRAM START
+ if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
+ adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
+ if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp));
+ binRecOutProgramStart(adr);
+ break;
+ case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
+ break;
+ default:
+ break;
+ }
+ return(TRUE);
+}
+
+
+//=============================================================================
+// MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY
+//=============================================================================
+
+int srec2bin(int argc,char *argv[],int verbose)
+{
+ int i,rlen,sts;
+ FILE *fp;
+ char ac;
+ char buff[256];
+ bit32u TAG_BIG = 0xDEADBE42;
+ bit32u TAG_LITTLE = 0xFEEDFA42;
+
+ bit32u Tag;
+
+
+ if(argc < 3)
+ {
+ printf("\nError: <srec2bin <srec input file> <bin output file>\n\n");
+ return(0);
+ }
+
+ if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE;
+
+ if (BigEndian)
+ Tag = TAG_BIG;
+ else
+ Tag = TAG_LITTLE;
+
+ if (verbose)
+ printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag);
+
+ fp = fopen(argv[1],"rt");
+
+ if (fp==NULL)
+ {
+ printf("\nError: Opening input file, %s.", argv[1]);
+ return(0);
+ }
+
+ fOut = fopen( argv[2], "wb");
+
+ if (fOut==NULL)
+ {
+ printf("\nError: Opening Output file, %s.", argv[2]);
+ if(fp) fclose(fp);
+ return(0);
+ }
+
+ RecStart = FALSE;
+
+ AddressCurrent = 0xFFFFFFFFL;
+
+ // Setup Tag
+
+ dumpfTell("Tag", Tag);
+
+ binOut32(Tag);
+
+
+ inputline=0;
+ sts=TRUE;
+
+ rlen = readline(fp,buff,sizeof buff);
+
+ while( (sts) && (rlen != -1))
+ {
+ if (strlen(buff))
+ {
+ sts &= srecLine(buff);
+ WaitDisplay();
+ }
+ rlen = readline(fp,buff,sizeof buff);
+ }
+
+
+ // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE);
+
+ binRecEnd();
+
+ if(fp) fclose(fp);
+ if(fOut) fclose(fOut);
+
+ return(1);
+}
+
+main(int argc, char *argv[])
+{
+ debug = TRUE;
+ debug = FALSE;
+ verbose = FALSE;
+ srec2bin(argc,argv,verbose);
+ return 0;
+}
+
diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c
new file mode 100644
index 0000000..77a894b
--- /dev/null
+++ b/tools/firmware-utils/src/tplink-safeloader.c
@@ -0,0 +1,559 @@
+/*
+ Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*
+ tplink-safeloader
+
+ Image generation tool for the TP-LINK SafeLoader as seen on
+ TP-LINK Pharos devices (CPE210/220/510/520)
+*/
+
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "md5.h"
+
+
+#define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
+
+
+/** An image partition table entry */
+struct image_partition_entry {
+ const char *name;
+ size_t size;
+ uint8_t *data;
+};
+
+/** A flash partition table entry */
+struct flash_partition_entry {
+ const char *name;
+ uint32_t base;
+ uint32_t size;
+};
+
+
+/** The content of the soft-version structure */
+struct __attribute__((__packed__)) soft_version {
+ uint32_t magic;
+ uint32_t zero;
+ uint8_t pad1;
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint8_t version_patch;
+ uint8_t year_hi;
+ uint8_t year_lo;
+ uint8_t month;
+ uint8_t day;
+ uint32_t rev;
+ uint8_t pad2;
+};
+
+
+static const uint8_t jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
+
+
+/**
+ Salt for the MD5 hash
+
+ Fortunately, TP-LINK seems to use the same salt for most devices which use
+ the new image format.
+*/
+static const uint8_t md5_salt[16] = {
+ 0x7a, 0x2b, 0x15, 0xed,
+ 0x9b, 0x98, 0x59, 0x6d,
+ 0xe5, 0x04, 0xab, 0x44,
+ 0xac, 0x2a, 0x9f, 0x4e,
+};
+
+
+/** Vendor information for CPE210/220/510/520 */
+static const char cpe510_vendor[] = "CPE510(TP-LINK|UN|N300-5):1.0\r\n";
+
+
+/**
+ The flash partition table for CPE210/220/510/520;
+ it is the same as the one used by the stock images.
+*/
+static const struct flash_partition_entry cpe510_partitions[] = {
+ {"fs-uboot", 0x00000, 0x20000},
+ {"partition-table", 0x20000, 0x02000},
+ {"default-mac", 0x30000, 0x00020},
+ {"product-info", 0x31100, 0x00100},
+ {"signature", 0x32000, 0x00400},
+ {"os-image", 0x40000, 0x170000},
+ {"soft-version", 0x1b0000, 0x00100},
+ {"support-list", 0x1b1000, 0x00400},
+ {"file-system", 0x1c0000, 0x600000},
+ {"user-config", 0x7c0000, 0x10000},
+ {"default-config", 0x7d0000, 0x10000},
+ {"log", 0x7e0000, 0x10000},
+ {"radio", 0x7f0000, 0x10000},
+ {NULL, 0, 0}
+};
+
+/**
+ The support list for CPE210/220/510/520
+*/
+static const char cpe510_support_list[] =
+ "SupportList:\r\n"
+ "CPE510(TP-LINK|UN|N300-5):1.0\r\n"
+ "CPE510(TP-LINK|UN|N300-5):1.1\r\n"
+ "CPE520(TP-LINK|UN|N300-5):1.0\r\n"
+ "CPE520(TP-LINK|UN|N300-5):1.1\r\n"
+ "CPE210(TP-LINK|UN|N300-2):1.0\r\n"
+ "CPE210(TP-LINK|UN|N300-2):1.1\r\n"
+ "CPE220(TP-LINK|UN|N300-2):1.0\r\n"
+ "CPE220(TP-LINK|UN|N300-2):1.1\r\n";
+
+#define error(_ret, _errno, _str, ...) \
+ do { \
+ fprintf(stderr, _str ": %s\n", ## __VA_ARGS__, \
+ strerror(_errno)); \
+ if (_ret) \
+ exit(_ret); \
+ } while (0)
+
+
+/** Stores a uint32 as big endian */
+static inline void put32(uint8_t *buf, uint32_t val) {
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+}
+
+/** Allocates a new image partition */
+static struct image_partition_entry alloc_image_partition(const char *name, size_t len) {
+ struct image_partition_entry entry = {name, len, malloc(len)};
+ if (!entry.data)
+ error(1, errno, "malloc");
+
+ return entry;
+}
+
+/** Frees an image partition */
+static void free_image_partition(struct image_partition_entry entry) {
+ free(entry.data);
+}
+
+/** Generates the partition-table partition */
+static struct image_partition_entry make_partition_table(const struct flash_partition_entry *p) {
+ struct image_partition_entry entry = alloc_image_partition("partition-table", 0x800);
+
+ char *s = (char *)entry.data, *end = (char *)(s+entry.size);
+
+ *(s++) = 0x00;
+ *(s++) = 0x04;
+ *(s++) = 0x00;
+ *(s++) = 0x00;
+
+ size_t i;
+ for (i = 0; p[i].name; i++) {
+ size_t len = end-s;
+ size_t w = snprintf(s, len, "partition %s base 0x%05x size 0x%05x\n", p[i].name, p[i].base, p[i].size);
+
+ if (w > len-1)
+ error(1, 0, "flash partition table overflow?");
+
+ s += w;
+ }
+
+ s++;
+
+ memset(s, 0xff, end-s);
+
+ return entry;
+}
+
+
+/** Generates a binary-coded decimal representation of an integer in the range [0, 99] */
+static inline uint8_t bcd(uint8_t v) {
+ return 0x10 * (v/10) + v%10;
+}
+
+
+/** Generates the soft-version partition */
+static struct image_partition_entry make_soft_version(uint32_t rev) {
+ struct image_partition_entry entry = alloc_image_partition("soft-version", sizeof(struct soft_version));
+ struct soft_version *s = (struct soft_version *)entry.data;
+
+ time_t t;
+
+ if (time(&t) == (time_t)(-1))
+ error(1, errno, "time");
+
+ struct tm *tm = localtime(&t);
+
+ s->magic = htonl(0x0000000c);
+ s->zero = 0;
+ s->pad1 = 0xff;
+
+ s->version_major = 0;
+ s->version_minor = 0;
+ s->version_patch = 0;
+
+ s->year_hi = bcd((1900+tm->tm_year)/100);
+ s->year_lo = bcd(tm->tm_year%100);
+ s->month = bcd(tm->tm_mon+1);
+ s->day = bcd(tm->tm_mday);
+ s->rev = htonl(rev);
+
+ s->pad2 = 0xff;
+
+ return entry;
+}
+
+/** Generates the support-list partition */
+static struct image_partition_entry make_support_list(const char *support_list) {
+ size_t len = strlen(support_list);
+ struct image_partition_entry entry = alloc_image_partition("support-list", len + 9);
+
+ put32(entry.data, len);
+ memset(entry.data+4, 0, 4);
+ memcpy(entry.data+8, support_list, len);
+ entry.data[len+8] = '\xff';
+
+ return entry;
+}
+
+/** Creates a new image partition with an arbitrary name from a file */
+static struct image_partition_entry read_file(const char *part_name, const char *filename, bool add_jffs2_eof) {
+ struct stat statbuf;
+
+ if (stat(filename, &statbuf) < 0)
+ error(1, errno, "unable to stat file `%s'", filename);
+
+ size_t len = statbuf.st_size;
+
+ if (add_jffs2_eof)
+ len = ALIGN(len, 0x10000) + sizeof(jffs2_eof_mark);
+
+ struct image_partition_entry entry = alloc_image_partition(part_name, len);
+
+ FILE *file = fopen(filename, "rb");
+ if (!file)
+ error(1, errno, "unable to open file `%s'", filename);
+
+ if (fread(entry.data, statbuf.st_size, 1, file) != 1)
+ error(1, errno, "unable to read file `%s'", filename);
+
+ if (add_jffs2_eof) {
+ uint8_t *eof = entry.data + statbuf.st_size, *end = entry.data+entry.size;
+
+ memset(eof, 0xff, end - eof - sizeof(jffs2_eof_mark));
+ memcpy(end - sizeof(jffs2_eof_mark), jffs2_eof_mark, sizeof(jffs2_eof_mark));
+ }
+
+ fclose(file);
+
+ return entry;
+}
+
+
+/**
+ Copies a list of image partitions into an image buffer and generates the image partition table while doing so
+
+ Example image partition table:
+
+ fwup-ptn partition-table base 0x00800 size 0x00800
+ fwup-ptn os-image base 0x01000 size 0x113b45
+ fwup-ptn file-system base 0x114b45 size 0x1d0004
+ fwup-ptn support-list base 0x2e4b49 size 0x000d1
+
+ Each line of the partition table is terminated with the bytes 09 0d 0a ("\t\r\n"),
+ the end of the partition table is marked with a zero byte.
+
+ The firmware image must contain at least the partition-table and support-list partitions
+ to be accepted. There aren't any alignment constraints for the image partitions.
+
+ The partition-table partition contains the actual flash layout; partitions
+ from the image partition table are mapped to the corresponding flash partitions during
+ the firmware upgrade. The support-list partition contains a list of devices supported by
+ the firmware image.
+
+ The base offsets in the firmware partition table are relative to the end
+ of the vendor information block, so the partition-table partition will
+ actually start at offset 0x1814 of the image.
+
+ I think partition-table must be the first partition in the firmware image.
+*/
+static void put_partitions(uint8_t *buffer, const struct image_partition_entry *parts) {
+ size_t i;
+ char *image_pt = (char *)buffer, *end = image_pt + 0x800;
+
+ size_t base = 0x800;
+ for (i = 0; parts[i].name; i++) {
+ memcpy(buffer + base, parts[i].data, parts[i].size);
+
+ size_t len = end-image_pt;
+ size_t w = snprintf(image_pt, len, "fwup-ptn %s base 0x%05x size 0x%05x\t\r\n", parts[i].name, (unsigned)base, (unsigned)parts[i].size);
+
+ if (w > len-1)
+ error(1, 0, "image partition table overflow?");
+
+ image_pt += w;
+
+ base += parts[i].size;
+ }
+
+ image_pt++;
+
+ memset(image_pt, 0xff, end-image_pt);
+}
+
+/** Generates and writes the image MD5 checksum */
+static void put_md5(uint8_t *md5, uint8_t *buffer, unsigned int len) {
+ MD5_CTX ctx;
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, md5_salt, (unsigned int)sizeof(md5_salt));
+ MD5_Update(&ctx, buffer, len);
+ MD5_Final(md5, &ctx);
+}
+
+
+/**
+ Generates the firmware image in factory format
+
+ Image format:
+
+ Bytes (hex) Usage
+ ----------- -----
+ 0000-0003 Image size (4 bytes, big endian)
+ 0004-0013 MD5 hash (hash of a 16 byte salt and the image data starting with byte 0x14)
+ 0014-0017 Vendor information length (without padding) (4 bytes, big endian)
+ 0018-1013 Vendor information (4092 bytes, padded with 0xff; there seem to be older
+ (VxWorks-based) TP-LINK devices which use a smaller vendor information block)
+ 1014-1813 Image partition table (2048 bytes, padded with 0xff)
+ 1814-xxxx Firmware partitions
+*/
+static void * generate_factory_image(const char *vendor, const struct image_partition_entry *parts, size_t *len) {
+ *len = 0x1814;
+
+ size_t i;
+ for (i = 0; parts[i].name; i++)
+ *len += parts[i].size;
+
+ uint8_t *image = malloc(*len);
+ if (!image)
+ error(1, errno, "malloc");
+
+ put32(image, *len);
+
+ size_t vendor_len = strlen(vendor);
+ put32(image+0x14, vendor_len);
+ memcpy(image+0x18, vendor, vendor_len);
+ memset(image+0x18+vendor_len, 0xff, 4092-vendor_len);
+
+ put_partitions(image + 0x1014, parts);
+ put_md5(image+0x04, image+0x14, *len-0x14);
+
+ return image;
+}
+
+/**
+ Generates the firmware image in sysupgrade format
+
+ This makes some assumptions about the provided flash and image partition tables and
+ should be generalized when TP-LINK starts building its safeloader into hardware with
+ different flash layouts.
+*/
+static void * generate_sysupgrade_image(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len) {
+ const struct flash_partition_entry *flash_os_image = &flash_parts[5];
+ const struct flash_partition_entry *flash_soft_version = &flash_parts[6];
+ const struct flash_partition_entry *flash_support_list = &flash_parts[7];
+ const struct flash_partition_entry *flash_file_system = &flash_parts[8];
+
+ const struct image_partition_entry *image_os_image = &image_parts[3];
+ const struct image_partition_entry *image_soft_version = &image_parts[1];
+ const struct image_partition_entry *image_support_list = &image_parts[2];
+ const struct image_partition_entry *image_file_system = &image_parts[4];
+
+ assert(strcmp(flash_os_image->name, "os-image") == 0);
+ assert(strcmp(flash_soft_version->name, "soft-version") == 0);
+ assert(strcmp(flash_support_list->name, "support-list") == 0);
+ assert(strcmp(flash_file_system->name, "file-system") == 0);
+
+ assert(strcmp(image_os_image->name, "os-image") == 0);
+ assert(strcmp(image_soft_version->name, "soft-version") == 0);
+ assert(strcmp(image_support_list->name, "support-list") == 0);
+ assert(strcmp(image_file_system->name, "file-system") == 0);
+
+ if (image_os_image->size > flash_os_image->size)
+ error(1, 0, "kernel image too big (more than %u bytes)", (unsigned)flash_os_image->size);
+ if (image_file_system->size > flash_file_system->size)
+ error(1, 0, "rootfs image too big (more than %u bytes)", (unsigned)flash_file_system->size);
+
+ *len = flash_file_system->base - flash_os_image->base + image_file_system->size;
+
+ uint8_t *image = malloc(*len);
+ if (!image)
+ error(1, errno, "malloc");
+
+ memset(image, 0xff, *len);
+
+ memcpy(image, image_os_image->data, image_os_image->size);
+ memcpy(image + flash_soft_version->base - flash_os_image->base, image_soft_version->data, image_soft_version->size);
+ memcpy(image + flash_support_list->base - flash_os_image->base, image_support_list->data, image_support_list->size);
+ memcpy(image + flash_file_system->base - flash_os_image->base, image_file_system->data, image_file_system->size);
+
+ return image;
+}
+
+
+/** Generates an image for CPE210/220/510/520 and writes it to a file */
+static void do_cpe510(const char *output, const char *kernel_image, const char *rootfs_image, uint32_t rev, bool add_jffs2_eof, bool sysupgrade) {
+ struct image_partition_entry parts[6] = {};
+
+ parts[0] = make_partition_table(cpe510_partitions);
+ parts[1] = make_soft_version(rev);
+ parts[2] = make_support_list(cpe510_support_list);
+ parts[3] = read_file("os-image", kernel_image, false);
+ parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof);
+
+ size_t len;
+ void *image;
+ if (sysupgrade)
+ image = generate_sysupgrade_image(cpe510_partitions, parts, &len);
+ else
+ image = generate_factory_image(cpe510_vendor, parts, &len);
+
+ FILE *file = fopen(output, "wb");
+ if (!file)
+ error(1, errno, "unable to open output file");
+
+ if (fwrite(image, len, 1, file) != 1)
+ error(1, 0, "unable to write output file");
+
+ fclose(file);
+
+ free(image);
+
+ size_t i;
+ for (i = 0; parts[i].name; i++)
+ free_image_partition(parts[i]);
+}
+
+
+/** Usage output */
+static void usage(const char *argv0) {
+ fprintf(stderr,
+ "Usage: %s [OPTIONS...]\n"
+ "\n"
+ "Options:\n"
+ " -B <board> create image for the board specified with <board>\n"
+ " -k <file> read kernel image from the file <file>\n"
+ " -r <file> read rootfs image from the file <file>\n"
+ " -o <file> write output to the file <file>\n"
+ " -V <rev> sets the revision number to <rev>\n"
+ " -j add jffs2 end-of-filesystem markers\n"
+ " -S create sysupgrade instead of factory image\n"
+ " -h show this help\n",
+ argv0
+ );
+};
+
+
+int main(int argc, char *argv[]) {
+ const char *board = NULL, *kernel_image = NULL, *rootfs_image = NULL, *output = NULL;
+ bool add_jffs2_eof = false, sysupgrade = false;
+ unsigned rev = 0;
+
+ while (true) {
+ int c;
+
+ c = getopt(argc, argv, "B:k:r:o:V:jSh");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'B':
+ board = optarg;
+ break;
+
+ case 'k':
+ kernel_image = optarg;
+ break;
+
+ case 'r':
+ rootfs_image = optarg;
+ break;
+
+ case 'o':
+ output = optarg;
+ break;
+
+ case 'V':
+ sscanf(optarg, "r%u", &rev);
+ break;
+
+ case 'j':
+ add_jffs2_eof = true;
+ break;
+
+ case 'S':
+ sysupgrade = true;
+ break;
+
+ case 'h':
+ usage(argv[0]);
+ return 0;
+
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ if (!board)
+ error(1, 0, "no board has been specified");
+ if (!kernel_image)
+ error(1, 0, "no kernel image has been specified");
+ if (!rootfs_image)
+ error(1, 0, "no rootfs image has been specified");
+ if (!output)
+ error(1, 0, "no output filename has been specified");
+
+ if (strcmp(board, "CPE510") == 0)
+ do_cpe510(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade);
+ else
+ error(1, 0, "unsupported board %s", board);
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/trx.c b/tools/firmware-utils/src/trx.c
new file mode 100644
index 0000000..aa1f5be
--- /dev/null
+++ b/tools/firmware-utils/src/trx.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* July 29, 2004
+ *
+ * This is a hacked replacement for the 'trx' utility used to create
+ * wrt54g .trx firmware files. It isn't pretty, but it does the job
+ * for me.
+ *
+ * As an extension, you can specify a larger maximum length for the
+ * .trx file using '-m'. It will be rounded up to be a multiple of 4K.
+ * NOTE: This space will be malloc()'d.
+ *
+ * August 16, 2004
+ *
+ * Sigh... Make it endian-neutral.
+ *
+ * TODO: Support '-b' option to specify offsets for each file.
+ *
+ * February 19, 2005 - mbm
+ *
+ * Add -a (align offset) and -b (absolute offset)
+ *
+ * March 24, 2010 - markus
+ *
+ * extend trx header struct for new version
+ * assume v1 for as default
+ * Add option -2 to allow v2 header
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X) bswap_32(X)
+#define LOAD32_LE(X) bswap_32(X)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X) (X)
+#define LOAD32_LE(X) (X)
+#else
+#error unkown endianness!
+#endif
+
+uint32_t crc32buf(char *buf, size_t len);
+
+/**********************************************************************/
+/* from trxhdr.h */
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+#define TRX_MAX_LEN 0x720000
+#define TRX_NO_HEADER 1 /* Do not write TRX header */
+
+struct trx_header {
+ uint32_t magic; /* "HDR0" */
+ uint32_t len; /* Length of file including header */
+ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */
+ uint32_t flag_version; /* 0:15 flags, 16:31 version */
+ uint32_t offsets[4]; /* Offsets of partitions from start of header */
+};
+
+/**********************************************************************/
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " trx [-2] [-o outfile] [-m maxlen] [-a align] [-b absolute offset] [-x relative offset]\n");
+ fprintf(stderr, " [-f file] [-f file [-f file [-f file (v2 only)]]]\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ FILE *out = stdout;
+ FILE *in;
+ char *ofn = NULL;
+ char *buf;
+ char *e;
+ int c, i, append = 0;
+ size_t n;
+ ssize_t n2;
+ uint32_t cur_len, fsmark=0;
+ unsigned long maxlen = TRX_MAX_LEN;
+ struct trx_header *p;
+ char trx_version = 1;
+ unsigned char binheader[32];
+
+ fprintf(stderr, "mjn3's trx replacement - v0.81.1\n");
+
+ if (!(buf = malloc(maxlen))) {
+ fprintf(stderr, "malloc failed\n");
+ return EXIT_FAILURE;
+ }
+
+ p = (struct trx_header *) buf;
+
+ p->magic = STORE32_LE(TRX_MAGIC);
+ cur_len = sizeof(struct trx_header) - 4; /* assume v1 header */
+
+ in = NULL;
+ i = 0;
+
+ while ((c = getopt(argc, argv, "-:2o:m:a:x:b:f:A:F:")) != -1) {
+ switch (c) {
+ case '2':
+ /* take care that nothing was written to buf so far */
+ if (cur_len != sizeof(struct trx_header) - 4) {
+ fprintf(stderr, "-2 has to be used before any other argument!\n");
+ }
+ else {
+ trx_version = 2;
+ cur_len += 4;
+ }
+ break;
+ case 'F':
+ fsmark = cur_len;
+ case 'A':
+ append = 1;
+ /* fall through */
+ case 'f':
+ case 1:
+ if (!append)
+ p->offsets[i++] = STORE32_LE(cur_len);
+
+ if (!(in = fopen(optarg, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", optarg);
+ usage();
+ }
+ n = fread(buf + cur_len, 1, maxlen - cur_len, in);
+ if (!feof(in)) {
+ fprintf(stderr, "fread failure or file \"%s\" too large\n",optarg);
+ fclose(in);
+ return EXIT_FAILURE;
+ }
+ fclose(in);
+#undef ROUND
+#define ROUND 4
+ if (n & (ROUND-1)) {
+ memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1)));
+ n += ROUND - (n & (ROUND-1));
+ }
+ cur_len += n;
+ append = 0;
+
+ break;
+ case 'o':
+ ofn = optarg;
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+ break;
+ case 'm':
+ errno = 0;
+ maxlen = strtoul(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+#undef ROUND
+#define ROUND 0x1000
+ if (maxlen & (ROUND-1)) {
+ maxlen += (ROUND - (maxlen & (ROUND-1)));
+ }
+ if (maxlen < ROUND) {
+ fprintf(stderr, "maxlen too small (or wrapped)\n");
+ usage();
+ }
+ if (maxlen > TRX_MAX_LEN) {
+ fprintf(stderr, "WARNING: maxlen exceeds default maximum! Beware of overwriting nvram!\n");
+ }
+ if (!(buf = realloc(buf,maxlen))) {
+ fprintf(stderr, "realloc failed");
+ return EXIT_FAILURE;
+ }
+ p = (struct trx_header *) buf;
+ break;
+ case 'a':
+ errno = 0;
+ n = strtoul(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+ if (cur_len & (n-1)) {
+ n = n - (cur_len & (n-1));
+ memset(buf + cur_len, 0, n);
+ cur_len += n;
+ }
+ break;
+ case 'b':
+ errno = 0;
+ n = strtoul(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+ if (n < cur_len) {
+ fprintf(stderr, "WARNING: current length exceeds -b %d offset\n",(int) n);
+ } else {
+ memset(buf + cur_len, 0, n - cur_len);
+ cur_len = n;
+ }
+ break;
+ case 'x':
+ errno = 0;
+ n2 = strtol(optarg, &e, 0);
+ if (errno || (e == optarg) || *e) {
+ fprintf(stderr, "illegal numeric string\n");
+ usage();
+ }
+ if (n2 < 0) {
+ if (-n2 > cur_len) {
+ fprintf(stderr, "WARNING: current length smaller then -x %d offset\n",(int) n2);
+ cur_len = 0;
+ } else
+ cur_len += n2;
+ } else {
+ memset(buf + cur_len, 0, n2);
+ cur_len += n2;
+ }
+
+ break;
+ default:
+ usage();
+ }
+ }
+ p->flag_version = STORE32_LE((trx_version << 16));
+
+ if (!in) {
+ fprintf(stderr, "we require atleast one filename\n");
+ usage();
+ }
+
+#undef ROUND
+#define ROUND 0x1000
+ n = cur_len & (ROUND-1);
+ if (n) {
+ memset(buf + cur_len, 0, ROUND - n);
+ cur_len += ROUND - n;
+ }
+
+ /* for TRXv2 set bin-header Flags to 0xFF for CRC calculation like CFE does */
+ if (trx_version == 2) {
+ if(cur_len - LOAD32_LE(p->offsets[3]) < sizeof(binheader)) {
+ fprintf(stderr, "TRXv2 binheader too small!\n");
+ return EXIT_FAILURE;
+ }
+ memcpy(binheader, buf + LOAD32_LE(p->offsets[3]), sizeof(binheader)); /* save header */
+ memset(buf + LOAD32_LE(p->offsets[3]) + 22, 0xFF, 8); /* set stable and try1-3 to 0xFF */
+ }
+
+ p->crc32 = crc32buf((char *) &p->flag_version,
+ ((fsmark)?fsmark:cur_len) - offsetof(struct trx_header, flag_version));
+ p->crc32 = STORE32_LE(p->crc32);
+
+ p->len = STORE32_LE((fsmark) ? fsmark : cur_len);
+
+ /* restore TRXv2 bin-header */
+ if (trx_version == 2) {
+ memcpy(buf + LOAD32_LE(p->offsets[3]), binheader, sizeof(binheader));
+ }
+
+ if (!fwrite(buf, cur_len, 1, out) || fflush(out)) {
+ fprintf(stderr, "fwrite failed\n");
+ return EXIT_FAILURE;
+ }
+
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
+
+/**********************************************************************/
+/* The following was grabbed and tweaked from the old snippets collection
+ * of public domain C code. */
+
+/**********************************************************************\
+|* Demonstration program to compute the 32-bit CRC used as the frame *|
+|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
+|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
+|* protocol). The 32-bit FCS was added via the Federal Register, *|
+|* 1 June 1982, p.23798. I presume but don't know for certain that *|
+|* this polynomial is or will be included in CCITT V.41, which *|
+|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
+|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
+|* errors by a factor of 10^-5 over 16-bit FCS. *|
+\**********************************************************************/
+
+/* Copyright (C) 1986 Gary S. Brown. You may use this program, or
+ code or tables extracted from it, as desired without restriction.*/
+
+/* First, the polynomial itself and its table of feedback terms. The */
+/* polynomial is */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in */
+/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
+/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
+/* the MSB being 1. */
+
+/* Note that the usual hardware shift register implementation, which */
+/* is what we're using (we're merely optimizing it by doing eight-bit */
+/* chunks at a time) shifts bits into the lowest-order term. In our */
+/* implementation, that means shifting towards the right. Why do we */
+/* do it this way? Because the calculated CRC must be transmitted in */
+/* order from highest-order term to lowest-order term. UARTs transmit */
+/* characters in order from LSB to MSB. By storing the CRC this way, */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part. Reception works similarly. */
+
+/* The feedback terms table consists of 256, 32-bit entries. Notes: */
+/* */
+/* 1. The table can be generated at runtime if desired; code to do so */
+/* is shown later. It might not be obvious, but the feedback */
+/* terms simply represent the results of eight shift/xor opera- */
+/* tions for all combinations of data and CRC register values. */
+/* */
+/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
+/* be they sixteen or thirty-two bits wide. You simply choose the */
+/* appropriate table. Alternatively, because the table can be */
+/* generated at runtime, you can start by generating the table for */
+/* the polynomial in question and use exactly the same "updcrc", */
+/* if your application needn't simultaneously handle two CRC */
+/* polynomials. (Note, however, that XMODEM is strange.) */
+/* */
+/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
+/* of course, 32-bit entries work OK if the high 16 bits are zero. */
+/* */
+/* 4. The values must be right-shifted by eight bits by the "updcrc" */
+/* logic; the shift must be unsigned (bring in zeroes). On some */
+/* hardware you could probably optimize the shift in assembler by */
+/* using byte-swap instructions. */
+
+static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
+0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
+
+uint32_t crc32buf(char *buf, size_t len)
+{
+ uint32_t crc;
+
+ crc = 0xFFFFFFFF;
+
+ for ( ; len; --len, ++buf)
+ {
+ crc = UPDC32(*buf, crc);
+ }
+
+ return crc;
+}
diff --git a/tools/firmware-utils/src/trx2edips.c b/tools/firmware-utils/src/trx2edips.c
new file mode 100644
index 0000000..f8d068d
--- /dev/null
+++ b/tools/firmware-utils/src/trx2edips.c
@@ -0,0 +1,171 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X) bswap_32(X)
+#define LOAD32_LE(X) bswap_32(X)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X) (X)
+#define LOAD32_LE(X) (X)
+#else
+#error unkown endianness!
+#endif
+
+/**********************************************************************/
+/* from trxhdr.h */
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+#define TRX_VERSION 1
+#define TRX_MAX_LEN 0x5A0000
+#define TRX_NO_HEADER 1 /* Do not write TRX header */
+
+struct trx_header {
+ uint32_t magic; /* "HDR0" */
+ uint32_t len; /* Length of file including header */
+ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */
+ uint32_t flag_version; /* 0:15 flags, 16:31 version */
+ uint32_t offsets[3]; /* Offsets of partitions from start of header */
+};
+
+
+struct edimax_header {
+ uint32_t sign; /* signature for header */
+ uint32_t length; /* start address but doesn't seems to be used... */
+ uint32_t start_addr; /* length of data, not used too ...*/
+};
+
+
+#define EDIMAX_PS16 0x36315350 /* "PS16" */
+#define EDIMAX_HDR_LEN 0xc
+
+
+/**********************************************************************/
+static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
+0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
+
+uint32_t crc32buf(char *buf, size_t len)
+{
+ uint32_t crc;
+
+ crc = 0xFFFFFFFF;
+
+ for (; len; --len, ++buf)
+ crc = UPDC32(*buf, crc);
+
+ return crc;
+}
+
+
+int main(int argc, char *argv[])
+{
+ FILE *fpIn = NULL;
+ FILE *fpOut = NULL;
+ struct edimax_header eh;
+ size_t res;
+ int length;
+
+ char *buf;
+ struct trx_header *p;
+
+ if (argc != 3) {
+ printf("Usage: %s <input file> <output file>\n", argv[0]);
+ return -1;
+ }
+
+ fpIn = fopen(argv[1], "rb");
+ if (fpIn == NULL) {
+ fprintf(stderr, "Unable to open %s\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+ /* compute the length of the file */
+ fseek(fpIn, 0, SEEK_END);
+ length = ftell(fpIn);
+ /* alloc enough memory to store the file */
+ buf = (char *)malloc(length);
+ if (!buf) {
+ fprintf(stderr, "malloc of buffers failed\n");
+ return EXIT_FAILURE;
+ }
+
+ rewind(fpIn);
+ /* read the whole file*/
+ res = fread(buf, 1, length, fpIn);
+
+ p = (struct trx_header *)buf;
+ if (LOAD32_LE(p->magic) != TRX_MAGIC) {
+ fprintf(stderr, "Not a trx file...%x\n", LOAD32_LE(p->magic));
+ return EXIT_FAILURE;
+ }
+
+ fclose(fpIn);
+
+ fpOut = fopen(argv[2], "wb+");
+ if (fpOut == NULL) {
+ fprintf(stderr, "Unable to open %s\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+ /* make the 3 partition beeing 12 bytes closer from the header */
+ memcpy(buf + LOAD32_LE(p->offsets[2]) - EDIMAX_HDR_LEN, buf + LOAD32_LE(p->offsets[2]), length - LOAD32_LE(p->offsets[2]));
+ /* recompute the crc32 check */
+ p->crc32 = STORE32_LE(crc32buf((char *) &p->flag_version, length - offsetof(struct trx_header, flag_version)));
+
+ eh.sign = STORE32_LE(EDIMAX_PS16);
+ eh.length = STORE32_LE(length);
+ eh.start_addr = STORE32_LE(0x80500000);
+
+ /* write the modified file */
+ fwrite(&eh, sizeof(struct edimax_header), 1, fpOut);
+ fwrite(buf, sizeof(char), length, fpOut);
+ fclose(fpOut);
+}
+
diff --git a/tools/firmware-utils/src/trx2usr.c b/tools/firmware-utils/src/trx2usr.c
new file mode 100644
index 0000000..96c0ab2
--- /dev/null
+++ b/tools/firmware-utils/src/trx2usr.c
@@ -0,0 +1,186 @@
+/*
+ * trx2usr - Convert a TRX firmware image to a U.S. Robotics firmware
+ * image by prepending a 28-byte header.
+ *
+ * This program was modeled after the usr-hdr.c program from the GPL'ed
+ * firmware for the U.S. Robotics Wireless MAXg Router (USR5461). The
+ * output file of this program can be uploaded via the web interface
+ * of the original U.S. Robotics firmware. Note that this program only
+ * works on a little-endian host platform.
+ *
+ * Copyright (C) 2006 Dick Streefland
+ *
+ * This is free software, licensed under the terms of the GNU General
+ * Public License as published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define TRX_MAGIC "HDR0"
+
+#define USR_MAGIC 0x30525355 // "USR0"
+#define EPI_VERSION 0x06235d03
+#define COMPAT_ID 1 // USR5461
+#define HARDWARE_REV 1
+
+#define CRC32_INIT 0xffffffff
+#define CHUNK (64*1024)
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+struct usr_header
+{
+ uint32 magic; // "USR0"
+ uint32 len; // file length without this header
+ uint32 crc32; // CRC32 of the file without header
+ uint32 version; // EPI_VERSION
+ uint16 compatibility_id; // COMPAT_ID
+ uint16 hardware_revision; // HARDWARE_REV
+ uint32 reserved[2];
+};
+
+static const uint32 crc_32_tab [] = // CRC polynomial 0xedb88320
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static char buf[CHUNK];
+
+static uint32 crc32(uint32 crc, uint8* p, size_t n)
+{
+ while (n--)
+ {
+ crc = crc_32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ }
+ return crc;
+}
+
+static int trx2usr(FILE* trx, FILE* usr)
+{
+ struct usr_header hdr;
+ size_t n;
+
+ hdr.magic = USR_MAGIC;
+ hdr.len = 0;
+ hdr.crc32 = CRC32_INIT;
+ hdr.version = EPI_VERSION;
+ hdr.compatibility_id = COMPAT_ID;
+ hdr.hardware_revision = HARDWARE_REV;
+ hdr.reserved[0] = 0;
+ hdr.reserved[1] = 0;
+ fwrite(& hdr, sizeof(hdr), 1, usr);
+ while ((n = fread(buf, 1, CHUNK, trx)))
+ {
+ if (hdr.len == 0 && strncmp(buf, TRX_MAGIC, strlen(TRX_MAGIC)) != 0)
+ {
+ break;
+ }
+ fwrite(& buf, 1, n, usr);
+ hdr.len += n;
+ hdr.crc32 = crc32( hdr.crc32, (uint8 *) & buf, n);
+ }
+ fseek(usr, 0L, SEEK_SET);
+ fwrite(& hdr, sizeof(hdr), 1, usr);
+ if (n != 0)
+ {
+ fprintf(stderr, "Input is not a TRX file\n");
+ return 1;
+ }
+ if (hdr.len == 0)
+ {
+ fprintf(stderr, "Empty input\n");
+ return 1;
+ }
+ if (ferror(trx))
+ {
+ fprintf(stderr, "Read error\n");
+ return 1;
+ }
+ if (ferror(usr))
+ {
+ fprintf(stderr, "Write error\n");
+ return 1;
+ }
+ return 0;
+}
+
+extern int main(int argc, char *argv[])
+{
+ FILE* in;
+ FILE* out;
+ int ret;
+
+ if (argc != 3)
+ {
+ fprintf(stderr, "Usage: trx2usr <trx input> <usr output>\n");
+ exit(2);
+ }
+ in = fopen(argv[1], "rb");
+ if (!in)
+ {
+ fprintf(stderr, "Cannot open \"%s\": %s\n", argv[1], strerror(errno));
+ exit(1);
+ }
+ out = fopen(argv[2], "wb");
+ if (!out)
+ {
+ fprintf(stderr, "Cannot create \"%s\": %s\n", argv[2], strerror(errno));
+ exit(1);
+ }
+ ret = trx2usr(in, out);
+ fclose(in);
+ fclose(out);
+ if (ret)
+ {
+ unlink(argv[2]);
+ }
+ return ret;
+}
diff --git a/tools/firmware-utils/src/wrt400n.c b/tools/firmware-utils/src/wrt400n.c
new file mode 100644
index 0000000..a9a4908
--- /dev/null
+++ b/tools/firmware-utils/src/wrt400n.c
@@ -0,0 +1,334 @@
+/*
+ * WRT400n - Firmware Generation Creator
+ *
+ * Creates a firmware image for the Linksys WRT400n router,
+ * that can be uploaded via the firmware upload page,
+ * from a kernel image file and root fs file
+ *
+ * Author: Sandeep Mistry
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "cyg_crc.h"
+
+// https://dev.openwrt.org/browser/trunk/target/linux/rdc-2.6/files/drivers/mtd/maps/rdc3210.c
+static uint32_t crctab[257] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+ 0
+};
+
+static uint32_t crc32(uint8_t* buf, uint32_t len)
+{
+ register int i;
+ uint32_t sum;
+ register uint32_t s0;
+ s0 = ~0;
+ for (i = 0; i < len; i++)
+ {
+ s0 = (s0 >> 8) ^ crctab[(uint8_t) (s0 & 0xFF) ^ buf[i]];
+ }
+ sum = ~s0;
+ return sum;
+}
+
+#define HEADERSIZE 60
+#define MAGIC "GMTKRT400N"
+
+// global variables
+uint8_t kernelbuf[0x100000]; // kernel - lzma - uImage
+uint8_t rootfsbuf[0x2FFFC4]; // root - squashfs
+
+uint8_t buf[0x400000]; // buffer for image
+
+
+// Header format:
+//
+// GPL Tarball: http://downloads.linksysbycisco.com/downloads/WRT400N_1.0.01.19_US.tar,0.gz
+// File: WRT400N_1.0.01.19_US/FW_WRT400N_1.0.01.19_US_20081229/GTK/user/include/fw_upgrade.h
+//
+//
+// Struct:
+// typedef struct
+// {
+// UINT32 checksum; /* CRC32 */
+// UINT8 magic[11]; /* The value of GTIMG_MAGIC */
+// UINT32 kernel_length; /* The length of the kernel image */
+// //UINT32 kernel_entry_point; /* Kernel's entry point for RedBoot's information */
+// UINT32 kernel_upgrade_flag; /* Set to 1 if we need to upgrade the kernel parition of the Flash */
+// UINT32 rootfs_length; /* The length of the rootfs image */
+// //UINT32 rootfs_entry_point; /* Not in use */
+// UINT32 rootfs_upgrade_flag; /* Set to 1 if we need to upgrade the rootfs parition of the Flash */
+//
+// // Add 3 items by Vic Yu, 2006-05/10
+// UINT32 kernel_checksum;
+// UINT32 rootfs_checksum;
+// UINT32 fw_totalsize;
+// UINT32 reserved[4];
+// }imghdr_t , *pLinuxFWHeader_T;
+//
+//
+// Description
+// - checksum: CRC32 of kernel and root fs, back to back
+// - magic: GMTKRT400N
+// - kernel_length: kernel length in bytes
+// - kernel_upgrade_flag: should we upgrade the kernel - set to 1
+// - rootfs_length: root fs length in byte
+// - rootfs_upgrade_flag: should we upgrade the root fs - set to 1
+// - kernel_checksum: Gary S. Brown's 32 bit CRC algorithm for kernel, with remaining bits
+// set to 0xFF upto 0x100000 bytes (total length)
+// - rootfs_checksum: Gary S. Brown's 32 bit CRC algorithm for root fs, with remaining bits
+// set to 0xFF upto 0x2FFFC4 bytes (total length)
+// - fw_totalsize: total firmware image file length (header length + kernel length + root fs length)
+// - reserved[4]: reserved ??? - set to all 0xFF
+
+
+
+int main(int argc, char *argv[])
+{
+ // file descriptors ...
+ int kernelfd = -1;
+ int rootfsfd = -1;
+ int outfd = -1;
+
+ char* kernelfilename = NULL;
+ char* rootfsfilename = NULL;
+ char* outputfilename = NULL;
+
+ // file sizes
+ uint32_t kernelsize = 0;
+ uint32_t rootfssize = 0;
+ uint32_t totalsize = 0;
+
+ // header flags
+ uint32_t kernelflag = 0;
+ uint32_t rootfsflag = 0;
+
+ // checksums
+ uint32_t kernelchecksum = 0;
+ uint32_t rootfschecksum = 0;
+ uint32_t crc = 0;
+
+ if(argc != 4)
+ {
+ printf("Usage:\n\t%s <kernel file> <rootfs file> <output file>\n", argv[0]);
+ return 1;
+ }
+
+ kernelfilename = argv[1];
+ rootfsfilename = argv[2];
+ outputfilename = argv[3];
+
+ // Fill the kernel, rootfs, main buffer
+ memset(kernelbuf, 0xFF, sizeof(kernelbuf));
+ memset(rootfsbuf, 0xFF, sizeof(rootfsbuf));
+ memset(buf, 0xFF, sizeof(buf));
+
+ // open the kernel ..
+ kernelfd = open(kernelfilename, O_RDONLY);
+
+ if(kernelfd == -1)
+ {
+ printf("Error: opening '%s'\n", kernelfilename);
+ goto done;
+ }
+
+ // read in the kernel ...
+ kernelsize = read(kernelfd, kernelbuf, sizeof(kernelbuf));
+
+ if(kernelsize == -1)
+ {
+ printf("Error: reading '%s'\n", kernelfilename);
+ goto done;
+ }
+
+ // calculate the kernel checksum ...
+ kernelchecksum = cyg_crc32_accumulate(0, kernelbuf, sizeof(kernelbuf));
+
+ // print out stats
+ printf("%s: size %d (0x%x), crc32 = 0x%x\n", kernelfilename, kernelsize, kernelsize, kernelchecksum);
+
+
+ // open the root fs ..
+ rootfsfd = open(rootfsfilename, O_RDONLY);
+
+ if(rootfsfd == -1)
+ {
+ printf("Error: opening '%s'\n", rootfsfilename);
+ goto done;
+ }
+
+ // read in the root fs ..
+ rootfssize = read(rootfsfd, rootfsbuf, sizeof(rootfsbuf));
+
+ if(rootfssize == -1)
+ {
+ printf("Error: reading '%s'\n", rootfsfilename);
+ goto done;
+ }
+
+ // calculate the root fs checksum ...
+ rootfschecksum = cyg_crc32_accumulate(0, rootfsbuf, sizeof(rootfsbuf));
+
+ // print out stats
+ printf("%s: size %d (0x%x), crc32 = 0x%x\n", rootfsfilename, rootfssize, rootfssize, rootfschecksum);
+
+
+ // now for the header ...
+
+ totalsize = HEADERSIZE;
+
+ // copy over kernel
+ memcpy(buf + totalsize, kernelbuf, kernelsize);
+ totalsize += kernelsize;
+
+ // copy over root fs
+ memcpy(buf + totalsize, rootfsbuf, rootfssize);
+ totalsize += rootfssize;
+
+ // calculate crc
+ crc = crc32(buf + HEADERSIZE, totalsize - HEADERSIZE);
+
+ // print some stats out
+ printf("crc = 0x%x, total size = %d (0x%x)\n", crc, totalsize, totalsize);
+
+ // copy crc into header
+ crc = htonl(crc);
+ memcpy(buf, &crc, sizeof(crc));
+
+ // copy over magic
+ strcpy((char *)buf + 4, MAGIC);
+
+ // copy over kernel size
+ kernelsize = htonl(kernelsize);
+ memcpy(buf + 16, &kernelsize, sizeof(kernelsize));
+
+ // copy over kernal flag
+ kernelflag = htonl(0x1);
+ memcpy(buf + 20, &kernelflag, sizeof(kernelflag));
+
+ // copy over root fs size
+ rootfssize = htonl(rootfssize);
+ memcpy(buf + 24, &rootfssize, sizeof(rootfssize));
+
+ // copy over root fs flag
+ rootfsflag = htonl(0x1);
+ memcpy(buf + 28, &rootfsflag, sizeof(rootfsflag));
+
+ // copy over kernel check sum
+ kernelchecksum = htonl(kernelchecksum);
+ memcpy(buf + 32, &kernelchecksum, sizeof(kernelchecksum));
+
+ // copy over root fs checksum
+ rootfschecksum = htonl(rootfschecksum);
+ memcpy(buf + 36, &rootfschecksum, sizeof(rootfschecksum));
+
+ // copy over total size
+ totalsize = htonl(totalsize);
+ memcpy(buf + 40, &totalsize, sizeof(totalsize));
+
+ // undo the htonl (for write)
+ totalsize = htonl(totalsize);
+
+
+ // write out the file from the buffer
+ outfd = open(outputfilename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ if(outfd == -1)
+ {
+ printf("ERROR: opening '%s' for write\n", outputfilename);
+ }
+
+ write(outfd, buf, totalsize);
+
+done:
+ // close open fd's
+
+ if(kernelfd != -1)
+ {
+ close(kernelfd);
+ kernelfd = -1;
+ }
+
+ if(rootfsfd != -1)
+ {
+ close(rootfsfd);
+ rootfsfd = -1;
+ }
+
+ if(outfd != -1)
+ {
+ close(outfd);
+ outfd = -1;
+ }
+
+ return 0;
+}
diff --git a/tools/firmware-utils/src/xorimage.c b/tools/firmware-utils/src/xorimage.c
new file mode 100644
index 0000000..b5ab83f
--- /dev/null
+++ b/tools/firmware-utils/src/xorimage.c
@@ -0,0 +1,135 @@
+/*
+ * xorimage.c - partially based on OpenWrt's addpattern.c
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+static char default_pattern[] = "12345678";
+
+
+int xor_data(uint8_t *data, size_t len, const uint8_t *pattern, int p_len, int p_off)
+{
+ int offset = p_off;
+ while (len--) {
+ *data ^= pattern[offset];
+ data++;
+ offset = (offset + 1) % p_len;
+ }
+ return offset;
+}
+
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: xorimage [-i infile] [-o outfile] [-p <pattern>]\n");
+ exit(EXIT_FAILURE);
+}
+
+
+int main(int argc, char **argv)
+{
+ char buf[1024]; /* keep this at 1k or adjust garbage calc below */
+ FILE *in = stdin;
+ FILE *out = stdout;
+ char *ifn = NULL;
+ char *ofn = NULL;
+ const char *pattern = default_pattern;
+ int c;
+ int v0, v1, v2;
+ size_t n;
+ int p_len, p_off = 0;
+
+ while ((c = getopt(argc, argv, "i:o:p:h")) != -1) {
+ switch (c) {
+ case 'i':
+ ifn = optarg;
+ break;
+ case 'o':
+ ofn = optarg;
+ break;
+ case 'p':
+ pattern = optarg;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc || optind == 1) {
+ fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
+ usage();
+ }
+
+ if (ifn && !(in = fopen(ifn, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
+ usage();
+ }
+
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+ p_len = strlen(pattern);
+
+ if (p_len == 0) {
+ fprintf(stderr, "pattern cannot be empty\n");
+ usage();
+ }
+
+
+ while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
+ if (n < sizeof(buf)) {
+ if (ferror(in)) {
+ FREAD_ERROR:
+ fprintf(stderr, "fread error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ p_off = xor_data(buf, n, pattern, p_len, p_off);
+
+ if (!fwrite(buf, n, 1, out)) {
+ FWRITE_ERROR:
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (ferror(in)) {
+ goto FREAD_ERROR;
+ }
+
+ if (fflush(out)) {
+ goto FWRITE_ERROR;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/firmware-utils/src/zynos.h b/tools/firmware-utils/src/zynos.h
new file mode 100644
index 0000000..aaf0fc8
--- /dev/null
+++ b/tools/firmware-utils/src/zynos.h
@@ -0,0 +1,225 @@
+/*
+ *
+ * Copyright (C) 2007-2008 OpenWrt.org
+ * Copyright (C) 2007-2008 Gabor Juhos <juhosg at openwrt.org>
+ *
+ * This code was based on the information of the ZyXEL's firmware
+ * image format written by Kolja Waschk, can be found at:
+ * http://www.ixo.de/info/zyxel_uclinux
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#ifndef _ZYNOS_H
+#define _ZYNOS_H
+
+#define BOOTBASE_NAME_LEN 32
+#define BOOTBASE_MAC_LEN 6
+#define BOOTBASE_FEAT_LEN 22
+
+#define BOOTEXT_DEF_SIZE 0x18000
+
+struct zyn_bootbase_info {
+ char vendor[BOOTBASE_NAME_LEN]; /* Vendor name */
+ char model[BOOTBASE_NAME_LEN]; /* Model name */
+ uint32_t bootext_addr; /* absolute address of the Boot Extension */
+ uint16_t res0; /* reserved/unknown */
+ uint8_t sys_type; /* system type */
+ uint8_t res1; /* reserved/unknown */
+ uint16_t model_id; /* model id */
+ uint8_t feat_other[BOOTBASE_FEAT_LEN]; /* other feature bits */
+ uint8_t feat_main; /* main feature bits */
+ uint8_t res2; /* reserved/unknown */
+ uint8_t mac[BOOTBASE_MAC_LEN]; /* mac address */
+ uint8_t country; /* default country code */
+ uint8_t dbgflag; /* debug flag */
+} __attribute__((packed));
+
+#define ROMBIN_SIG_LEN 3
+#define ROMBIN_VER_LEN 15
+
+struct zyn_rombin_hdr {
+ uint32_t addr; /* load address of the object */
+ uint16_t res0; /* unknown/unused */
+ char sig[ROMBIN_SIG_LEN]; /* magic, must be "SIG" */
+ uint8_t type; /* type of the object */
+ uint32_t osize; /* size of the uncompressed data */
+ uint32_t csize; /* size of the compressed data */
+ uint8_t flags; /* various flags */
+ uint8_t res1; /* unknown/unused */
+ uint16_t ocsum; /* csum of the uncompressed data */
+ uint16_t ccsum; /* csum of the compressed data */
+ char ver[ROMBIN_VER_LEN];
+ uint32_t mmap_addr; /* address of the Memory Map Table*/
+ uint32_t res2; /* unknown/unused*/
+ uint8_t res3; /* unknown/unused*/
+} __attribute__((packed));
+
+#define ROMBIN_SIGNATURE "SIG"
+
+/* Rombin flag bits */
+#define ROMBIN_FLAG_01 0x01
+#define ROMBIN_FLAG_02 0x02
+#define ROMBIN_FLAG_04 0x04
+#define ROMBIN_FLAG_08 0x08
+#define ROMBIN_FLAG_10 0x10
+#define ROMBIN_FLAG_CCSUM 0x20 /* compressed checksum is valid */
+#define ROMBIN_FLAG_OCSUM 0x40 /* original checksum is valid */
+#define ROMBIN_FLAG_COMPRESSED 0x80 /* the binary is compressed */
+
+/* Object types */
+#define OBJECT_TYPE_ROMIMG 0x01
+#define OBJECT_TYPE_ROMBOOT 0x02
+#define OBJECT_TYPE_BOOTEXT 0x03
+#define OBJECT_TYPE_ROMBIN 0x04
+#define OBJECT_TYPE_ROMDIR 0x05
+#define OBJECT_TYPE_6 0x06
+#define OBJECT_TYPE_ROMMAP 0x07
+#define OBJECT_TYPE_RAM 0x80
+#define OBJECT_TYPE_RAMCODE 0x81
+#define OBJECT_TYPE_RAMBOOT 0x82
+
+/*
+ * Memory Map Table header
+ */
+struct zyn_mmt_hdr {
+ uint16_t count;
+ uint32_t user_start;
+ uint32_t user_end;
+ uint16_t csum;
+ uint8_t res[12];
+} __attribute__((packed));
+
+#define OBJECT_NAME_LEN 8
+
+struct zyn_mmt_item {
+ uint8_t type; /* type of the object */
+ uint8_t name[OBJECT_NAME_LEN]; /* name of the object */
+ uint8_t res0; /* unused/unknown */
+ uint32_t addr;
+ uint32_t size; /* size of the object */
+ uint8_t res1[3]; /* unused/unknown */
+ uint8_t type2;
+} __attribute__((packed));
+
+/*
+ * Vendor IDs
+ */
+#define ZYNOS_VENDOR_ID_ZYXEL 0
+#define ZYNOS_VENDOR_ID_NETGEAR 1
+#define ZYNOS_VENDOR_ID_DLINK 2
+#define ZYNOS_VENDOR_ID_03 3
+#define ZYNOS_VENDOR_ID_LUCENT 4
+#define ZYNOS_VENDOR_ID_O2 10
+
+/*
+ * Model IDs (in big-endian format)
+ */
+#define MID(x) (((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)
+
+/*
+ * Infineon/ADMtek ADM5120 based models
+ */
+#define ZYNOS_MODEL_ES_2024A MID( 221)
+#define ZYNOS_MODEL_ES_2024PWR MID( 4097)
+#define ZYNOS_MODEL_ES_2108 MID(61952)
+#define ZYNOS_MODEL_ES_2108_F MID(44801)
+#define ZYNOS_MODEL_ES_2108_G MID(62208)
+#define ZYNOS_MODEL_ES_2108_LC MID(64512)
+#define ZYNOS_MODEL_ES_2108PWR MID(62464)
+#define ZYNOS_MODEL_HS_100 MID(61855)
+#define ZYNOS_MODEL_HS_100W ZYNOS_MODEL_HS_100
+#define ZYNOS_MODEL_P_334 MID(62879)
+#define ZYNOS_MODEL_P_334U MID(56735)
+#define ZYNOS_MODEL_P_334W MID(62367)
+#define ZYNOS_MODEL_P_334WH MID(57344)
+#define ZYNOS_MODEL_P_334WHD MID(57600)
+#define ZYNOS_MODEL_P_334WT MID(61343)
+#define ZYNOS_MODEL_P_335 MID(60831)
+#define ZYNOS_MODEL_P_335PLUS MID( 9472)
+#define ZYNOS_MODEL_P_335U MID(56479)
+#define ZYNOS_MODEL_P_335WT ZYNOS_MODEL_P_335
+
+/*
+ * Texas Instruments AR7 based models
+ */
+#define ZYNOS_MODEL_P_2602H_61C MID( 3229)
+#define ZYNOS_MODEL_P_2602H_63C MID( 3485)
+#define ZYNOS_MODEL_P_2602H_D1A /* n.a. */
+#define ZYNOS_MODEL_P_2602H_D3A /* n.a. */
+#define ZYNOS_MODEL_P_2602HW_61C /* n.a. */
+#define ZYNOS_MODEL_P_2602HW_63 /* n.a. */
+#define ZYNOS_MODEL_P_2602HW_63C ZYNOS_MODEL_P_2602H_63C
+#define ZYNOS_MODEL_P_2602HW_D1A MID( 6301)
+#define ZYNOS_MODEL_P_2602HW_D3A /* n.a. */
+#define ZYNOS_MODEL_P_2602HWL_61 MID( 1181)
+#define ZYNOS_MODEL_P_2602HWL_61C ZYNOS_MODEL_P_2602H_61C
+#define ZYNOS_MODEL_P_2602HWL_63C ZYNOS_MODEL_P_2602H_63C
+#define ZYNOS_MODEL_P_2602HWL_D1A ZYNOS_MODEL_P_2602HW_D1A
+#define ZYNOS_MODEL_P_2602HWL_D3A MID( 7581)
+#define ZYNOS_MODEL_P_2602HWN_D7A MID(30464)
+#define ZYNOS_MODEL_P_2602HWNLI_D7A MID( 6813)
+
+#define ZYNOS_MODEL_P_2602R_61 MID( 2205)
+#define ZYNOS_MODEL_P_2602R_63 MID( 3997)
+#define ZYNOS_MODEL_P_2602R_D1A /* n.a. */
+#define ZYNOS_MODEL_P_2602R_D3A /* n.a. */
+#define ZYNOS_MODEL_P_2602RL_D1A MID( 6045)
+#define ZYNOS_MODEL_P_2602RL_D3A MID( 7069)
+
+#define ZYNOS_MODEL_P_660H_61 MID(19346)
+#define ZYNOS_MODEL_P_660H_63 MID(22162)
+#define ZYNOS_MODEL_P_660H_67 /* n.a. */
+#define ZYNOS_MODEL_P_660H_D1 MID( 7066)
+#define ZYNOS_MODEL_P_660H_D3 MID(13210)
+
+#define ZYNOS_MODEL_P_660HW_61 ZYNOS_MODEL_P_660H_61
+#define ZYNOS_MODEL_P_660HW_63 ZYNOS_MODEL_P_660H_63
+#define ZYNOS_MODEL_P_660HW_67 ZYNOS_MODEL_P_660HW_63
+#define ZYNOS_MODEL_P_660HW_D1 MID( 9114)
+#define ZYNOS_MODEL_P_660HW_D3 MID(12698)
+
+#define ZYNOS_MODEL_P_660R_61 MID(20882)
+#define ZYNOS_MODEL_P_660R_61C MID( 1178)
+#define ZYNOS_MODEL_P_660R_63 MID(21138)
+#define ZYNOS_MODEL_P_660R_63C MID( 922)
+#define ZYNOS_MODEL_P_660R_67 ZYNOS_MODEL_P_660R_63
+#define ZYNOS_MODEL_P_660R_67C /* n.a. */
+#define ZYNOS_MODEL_P_660R_D1 MID( 7322)
+#define ZYNOS_MODEL_P_660R_D3 MID(10138)
+
+#define ZYNOS_MODEL_P_661H_61 MID(19346)
+#define ZYNOS_MODEL_P_661H_63 MID( 1946)
+#define ZYNOS_MODEL_P_661H_D1 MID(10650)
+#define ZYNOS_MODEL_P_661H_D3 MID(12442)
+
+#define ZYNOS_MODEL_P_661HW_61 ZYNOS_MODEL_P_661H_61
+#define ZYNOS_MODEL_P_661HW_63 ZYNOS_MODEL_P_661H_63
+#define ZYNOS_MODEL_P_661HW_D1 MID(10906)
+#define ZYNOS_MODEL_P_661HW_D3 MID(14746)
+
+#define ZYNOS_MODEL_P_662H_61 MID(22418)
+#define ZYNOS_MODEL_P_662H_63 /* n.a. */
+#define ZYNOS_MODEL_P_662H_67 /* n.a. */
+#define ZYNOS_MODEL_P_662H_D1 /* n.a. */
+#define ZYNOS_MODEL_P_662H_D3 /* n.a. */
+
+#define ZYNOS_MODEL_P_662HW_61 /* n.a. */
+#define ZYNOS_MODEL_P_662HW_63 MID(22674)
+#define ZYNOS_MODEL_P_662HW_67 /* n.a. */
+#define ZYNOS_MODEL_P_662HW_D1 MID(10394)
+#define ZYNOS_MODEL_P_662HW_D3 MID(12954)
+
+/* OEM boards */
+#define ZYNOS_MODEL_O2SURF ZYNOS_MODEL_P_2602HWN_D7A
+
+/* Atheros AR2318 based boards */
+#define ZYNOS_MODEL_NBG_318S MID(59392)
+
+/* Atheros AR71xx based boards */
+#define ZYNOS_MODEL_NBG_460N MID(61441)
+
+#endif /* _ZYNOS_H */
diff --git a/tools/firmware-utils/src/zyxbcm.c b/tools/firmware-utils/src/zyxbcm.c
new file mode 100644
index 0000000..cfd00d3
--- /dev/null
+++ b/tools/firmware-utils/src/zyxbcm.c
@@ -0,0 +1,259 @@
+/*
+ * zyxbcm.c - based on Jonas Gorski's spw303v.c
+ *
+ * Copyright (C) 2014 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#define TAGVER_LEN 4 /* Length of Tag Version */
+#define SIG1_LEN 20 /* Company Signature 1 Length */
+#define SIG2_LEN 14 /* Company Signature 2 Lenght */
+#define BOARDID_LEN 16 /* Length of BoardId */
+#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
+#define CHIPID_LEN 6 /* Chip Id Length */
+#define IMAGE_LEN 10 /* Length of Length Field */
+#define ADDRESS_LEN 12 /* Length of Address field */
+#define DUALFLAG_LEN 2 /* Dual Image flag Length */
+#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
+#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
+#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
+#define ZYX_TAGINFO1_LEN 20 /* Length of vendor information field1 in tag */
+#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
+#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
+#define CRC_LEN 4 /* Length of CRC in bytes */
+
+#define IMAGETAG_CRC_START 0xFFFFFFFF
+
+struct bcm_tag {
+ char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
+ char sig_1[SIG1_LEN]; // 4-23: Company Line 1
+ char sig_2[SIG2_LEN]; // 24-37: Company Line 2
+ char chipid[CHIPID_LEN]; // 38-43: Chip this image is for
+ char boardid[BOARDID_LEN]; // 44-59: Board name
+ char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE
+ char totalLength[IMAGE_LEN]; // 62-71: Total length of image
+ char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
+ char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
+ char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware)
+ char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing
+ char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
+ char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
+ char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present
+ char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present
+ char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this)
+ char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT)
+ char flashLayoutVer[FLASHLAYOUTVER_LEN]; // 192-195: Version flash layout
+ char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32
+ char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information
+ char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate)
+ char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition
+ char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition
+ char imageSequence[4]; // 228-231: Image sequence number
+ char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot
+ char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion
+ char reserved2[16]; // 240-255: Unused at present
+};
+
+struct zyxbcm_tag {
+ char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
+ char sig_1[SIG1_LEN]; // 4-23: Company Line 1
+ char sig_2[SIG2_LEN]; // 24-37: Company Line 2
+ char chipid[CHIPID_LEN]; // 38-43: Chip this image is for
+ char boardid[BOARDID_LEN]; // 44-59: Board name
+ char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE
+ char totalLength[IMAGE_LEN]; // 62-71: Total length of image
+ char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
+ char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
+ char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware)
+ char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing
+ char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
+ char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
+ char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present
+ char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present
+ char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this)
+ char information1[ZYX_TAGINFO1_LEN]; // 162-181: Compilation and related information (not generated/used by OpenWRT)
+ char flashImageEnd[ADDRESS_LEN]; // 182-193: Address in memory of image end
+ char fskernelCRC[CRC_LEN]; // 194-197: kernel+rootfs CRC32
+ char reserved1[2]; // 198-199: Unused at present
+ char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information
+ char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate)
+ char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition
+ char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition
+ char imageSequence[4]; // 228-231: Image sequence number
+ char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot
+ char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion
+ char reserved2[16]; // 240-255: Unused at present
+};
+
+static uint32_t crc32tab[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+uint32_t crc32(uint32_t crc, uint8_t *data, size_t len)
+{
+ while (len--)
+ crc = (crc >> 8) ^ crc32tab[(crc ^ *data++) & 0xFF];
+
+ return crc;
+}
+
+void fix_header(void *buf)
+{
+ struct bcm_tag *bcmtag = buf;
+ struct zyxbcm_tag *zyxtag = buf;
+ uint8_t fskernel_crc[CRC_LEN];
+ uint32_t crc;
+ uint64_t flash_start, rootfs_len, kernel_len;
+
+ /* Backup values */
+ flash_start = strtoul(bcmtag->flashImageStart, NULL, 10);
+ rootfs_len = strtoul(bcmtag->flashRootLength, NULL, 10);
+ kernel_len = strtoul(bcmtag->kernelLength, NULL, 10);
+ memcpy(fskernel_crc, bcmtag->fskernelCRC, CRC_LEN);
+
+ /* Clear values */
+ zyxtag->information1[ZYX_TAGINFO1_LEN - 1] = 0;
+ memset(zyxtag->flashImageEnd, 0, ADDRESS_LEN);
+ memset(zyxtag->fskernelCRC, 0, CRC_LEN);
+ memset(zyxtag->reserved1, 0, 2);
+
+ /* Replace values */
+ sprintf(zyxtag->flashImageEnd, "%lu", flash_start + rootfs_len + kernel_len);
+ memcpy(zyxtag->fskernelCRC, fskernel_crc, CRC_LEN);
+
+ /* Update tag crc */
+ crc = htonl(crc32(IMAGETAG_CRC_START, buf, 236));
+ memcpy(zyxtag->headerCRC, &crc, 4);
+}
+
+void usage(void) __attribute__ (( __noreturn__ ));
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: zyxbcm [-i <inputfile>] [-o <outputfile>]\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ char buf[1024]; /* keep this at 1k or adjust garbage calc below */
+ FILE *in = stdin, *out = stdout;
+ char *ifn = NULL, *ofn = NULL;
+ size_t n;
+ int c, first_block = 1;
+
+ while ((c = getopt(argc, argv, "i:o:h")) != -1) {
+ switch (c) {
+ case 'i':
+ ifn = optarg;
+ break;
+ case 'o':
+ ofn = optarg;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+
+ if (optind != argc || optind == 1) {
+ fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
+ usage();
+ }
+
+ if (ifn && !(in = fopen(ifn, "r"))) {
+ fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
+ usage();
+ }
+
+ if (ofn && !(out = fopen(ofn, "w"))) {
+ fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
+ usage();
+ }
+
+ while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
+ if (n < sizeof(buf)) {
+ if (ferror(in)) {
+ FREAD_ERROR:
+ fprintf(stderr, "fread error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (first_block && n >= 256) {
+ fix_header(buf);
+ first_block = 0;
+ }
+
+ if (!fwrite(buf, n, 1, out)) {
+ FWRITE_ERROR:
+ fprintf(stderr, "fwrite error\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (ferror(in)) {
+ goto FREAD_ERROR;
+ }
+
+ if (fflush(out)) {
+ goto FWRITE_ERROR;
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/flex/Makefile b/tools/flex/Makefile
new file mode 100644
index 0000000..0e56ede
--- /dev/null
+++ b/tools/flex/Makefile
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2008-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=flex
+PKG_VERSION:=2.5.39
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@SF/$(PKG_NAME)
+PKG_MD5SUM:=77d44c6bb8c0705e0017ab9a84a1502b
+PKG_CAT:=bzcat
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += --disable-shared
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/flex/patches/100-remove_no_undefined.patch b/tools/flex/patches/100-remove_no_undefined.patch
new file mode 100644
index 0000000..4e8aca1
--- /dev/null
+++ b/tools/flex/patches/100-remove_no_undefined.patch
@@ -0,0 +1,18 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -73,13 +73,13 @@ libfl_la_SOURCES = \
+ libmain.c \
+ libyywrap.c
+
+-libfl_la_LDFLAGS = -no-undefined -version-info @SHARED_VERSION_INFO@
++libfl_la_LDFLAGS = -version-info @SHARED_VERSION_INFO@
+
+ libfl_pic_la_SOURCES = \
+ libmain.c \
+ libyywrap.c
+
+-libfl_pic_la_LDFLAGS = -no-undefined -version-info @SHARED_VERSION_INFO@
++libfl_pic_la_LDFLAGS = -version-info @SHARED_VERSION_INFO@
+
+ noinst_HEADERS = \
+ flexdef.h \
diff --git a/tools/flock/Makefile b/tools/flock/Makefile
new file mode 100644
index 0000000..a6a4758
--- /dev/null
+++ b/tools/flock/Makefile
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME := flock
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ mkdir -p $(HOST_BUILD_DIR)
+ $(HOSTCC) $(HOST_CFLAGS) -o $(HOST_BUILD_DIR)/flock src/flock.c
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/flock $(STAGING_DIR_HOST)/bin/
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/flock/src/flock.c b/tools/flock/src/flock.c
new file mode 100644
index 0000000..13baec4
--- /dev/null
+++ b/tools/flock/src/flock.c
@@ -0,0 +1,325 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2005 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <signal.h>
+#include <ctype.h>
+#include <string.h>
+#include <paths.h>
+#include <sysexits.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#define PACKAGE_STRING "util-linux-ng 2.18"
+#define _(x) (x)
+
+static const struct option long_options[] = {
+ { "shared", 0, NULL, 's' },
+ { "exclusive", 0, NULL, 'x' },
+ { "unlock", 0, NULL, 'u' },
+ { "nonblocking", 0, NULL, 'n' },
+ { "nb", 0, NULL, 'n' },
+ { "timeout", 1, NULL, 'w' },
+ { "wait", 1, NULL, 'w' },
+ { "close", 0, NULL, 'o' },
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { 0, 0, 0, 0 }
+};
+
+const char *program;
+
+static void usage(int ex)
+{
+ fputs("flock (" PACKAGE_STRING ")\n", stderr);
+ fprintf(stderr,
+ _("Usage: %1$s [-sxun][-w #] fd#\n"
+ " %1$s [-sxon][-w #] file [-c] command...\n"
+ " %1$s [-sxon][-w #] directory [-c] command...\n"
+ " -s --shared Get a shared lock\n"
+ " -x --exclusive Get an exclusive lock\n"
+ " -u --unlock Remove a lock\n"
+ " -n --nonblock Fail rather than wait\n"
+ " -w --timeout Wait for a limited amount of time\n"
+ " -o --close Close file descriptor before running command\n"
+ " -c --command Run a single command string through the shell\n"
+ " -h --help Display this text\n"
+ " -V --version Display version\n"),
+ program);
+ exit(ex);
+}
+
+
+static sig_atomic_t timeout_expired = 0;
+
+static void timeout_handler(int sig)
+{
+ (void)sig;
+
+ timeout_expired = 1;
+}
+
+
+static char * strtotimeval(const char *str, struct timeval *tv)
+{
+ char *s;
+ long fs; /* Fractional seconds */
+ int i;
+
+ tv->tv_sec = strtol(str, &s, 10);
+ fs = 0;
+
+ if ( *s == '.' ) {
+ s++;
+
+ for ( i = 0 ; i < 6 ; i++ ) {
+ if ( !isdigit(*s) )
+ break;
+
+ fs *= 10;
+ fs += *s++ - '0';
+ }
+
+ for ( ; i < 6; i++ )
+ fs *= 10;
+
+ while ( isdigit(*s) )
+ s++;
+ }
+
+ tv->tv_usec = fs;
+ return s;
+}
+
+int main(int argc, char *argv[])
+{
+ struct itimerval timeout, old_timer;
+ int have_timeout = 0;
+ int type = LOCK_EX;
+ int block = 0;
+ int fd = -1;
+ int opt, ix;
+ int do_close = 0;
+ int err;
+ int status;
+ char *eon;
+ char **cmd_argv = NULL, *sh_c_argv[4];
+ const char *filename = NULL;
+ struct sigaction sa, old_sa;
+
+ program = argv[0];
+
+ if ( argc < 2 )
+ usage(EX_USAGE);
+
+ memset(&timeout, 0, sizeof timeout);
+
+ optopt = 0;
+ while ( (opt = getopt_long(argc, argv, "+sexnouw:hV?", long_options, &ix)) != EOF ) {
+ switch(opt) {
+ case 's':
+ type = LOCK_SH;
+ break;
+ case 'e':
+ case 'x':
+ type = LOCK_EX;
+ break;
+ case 'u':
+ type = LOCK_UN;
+ break;
+ case 'o':
+ do_close = 1;
+ break;
+ case 'n':
+ block = LOCK_NB;
+ break;
+ case 'w':
+ have_timeout = 1;
+ eon = strtotimeval(optarg, &timeout.it_value);
+ if ( *eon )
+ usage(EX_USAGE);
+ break;
+ case 'V':
+ printf("flock (%s)\n", PACKAGE_STRING);
+ exit(0);
+ default:
+ /* optopt will be set if this was an unrecognized option, i.e. *not* 'h' or '?' */
+ usage(optopt ? EX_USAGE : 0);
+ break;
+ }
+ }
+
+ if ( argc > optind+1 ) {
+ /* Run command */
+
+ if ( !strcmp(argv[optind+1], "-c") ||
+ !strcmp(argv[optind+1], "--command") ) {
+
+ if ( argc != optind+3 ) {
+ fprintf(stderr, _("%s: %s requires exactly one command argument\n"),
+ program, argv[optind+1]);
+ exit(EX_USAGE);
+ }
+
+ cmd_argv = sh_c_argv;
+
+ cmd_argv[0] = getenv("SHELL");
+ if ( !cmd_argv[0] || !*cmd_argv[0] )
+ cmd_argv[0] = _PATH_BSHELL;
+
+ cmd_argv[1] = "-c";
+ cmd_argv[2] = argv[optind+2];
+ cmd_argv[3] = 0;
+ } else {
+ cmd_argv = &argv[optind+1];
+ }
+
+ filename = argv[optind];
+ fd = open(filename, O_RDONLY|O_NOCTTY|O_CREAT, 0666);
+ /* Linux doesn't like O_CREAT on a directory, even though it should be a
+ no-op */
+ if (fd < 0 && errno == EISDIR)
+ fd = open(filename, O_RDONLY|O_NOCTTY);
+
+ if ( fd < 0 ) {
+ err = errno;
+ fprintf(stderr, _("%s: cannot open lock file %s: %s\n"),
+ program, argv[optind], strerror(err));
+ exit((err == ENOMEM||err == EMFILE||err == ENFILE) ? EX_OSERR :
+ (err == EROFS||err == ENOSPC) ? EX_CANTCREAT :
+ EX_NOINPUT);
+ }
+
+ } else if (optind < argc) {
+ /* Use provided file descriptor */
+
+ fd = (int)strtol(argv[optind], &eon, 10);
+ if ( *eon || !argv[optind] ) {
+ fprintf(stderr, _("%s: bad number: %s\n"), program, argv[optind]);
+ exit(EX_USAGE);
+ }
+
+ } else {
+ /* Bad options */
+
+ fprintf(stderr, _("%s: requires file descriptor, file or directory\n"),
+ program);
+ exit(EX_USAGE);
+ }
+
+
+ if ( have_timeout ) {
+ if ( timeout.it_value.tv_sec == 0 &&
+ timeout.it_value.tv_usec == 0 ) {
+ /* -w 0 is equivalent to -n; this has to be special-cased
+ because setting an itimer to zero means disabled! */
+
+ have_timeout = 0;
+ block = LOCK_NB;
+ } else {
+ memset(&sa, 0, sizeof sa);
+
+ sa.sa_handler = timeout_handler;
+ sa.sa_flags = SA_RESETHAND;
+ sigaction(SIGALRM, &sa, &old_sa);
+
+ setitimer(ITIMER_REAL, &timeout, &old_timer);
+ }
+ }
+
+ while ( flock(fd, type|block) ) {
+ switch( (err = errno) ) {
+ case EWOULDBLOCK: /* -n option set and failed to lock */
+ exit(1);
+ case EINTR: /* Signal received */
+ if ( timeout_expired )
+ exit(1); /* -w option set and failed to lock */
+ continue; /* otherwise try again */
+ default: /* Other errors */
+ if ( filename )
+ fprintf(stderr, "%s: %s: %s\n", program, filename, strerror(err));
+ else
+ fprintf(stderr, "%s: %d: %s\n", program, fd, strerror(err));
+ exit((err == ENOLCK||err == ENOMEM) ? EX_OSERR : EX_DATAERR);
+ }
+ }
+
+ if ( have_timeout ) {
+ setitimer(ITIMER_REAL, &old_timer, NULL); /* Cancel itimer */
+ sigaction(SIGALRM, &old_sa, NULL); /* Cancel signal handler */
+ }
+
+ status = 0;
+
+ if ( cmd_argv ) {
+ pid_t w, f;
+
+ /* Clear any inherited settings */
+ signal(SIGCHLD, SIG_DFL);
+ f = fork();
+
+ if ( f < 0 ) {
+ err = errno;
+ fprintf(stderr, _("%s: fork failed: %s\n"), program, strerror(err));
+ exit(EX_OSERR);
+ } else if ( f == 0 ) {
+ if ( do_close )
+ close(fd);
+ err = errno;
+ execvp(cmd_argv[0], cmd_argv);
+ /* execvp() failed */
+ fprintf(stderr, "%s: %s: %s\n", program, cmd_argv[0], strerror(err));
+ _exit((err == ENOMEM) ? EX_OSERR: EX_UNAVAILABLE);
+ } else {
+ do {
+ w = waitpid(f, &status, 0);
+ if (w == -1 && errno != EINTR)
+ break;
+ } while ( w != f );
+
+ if (w == -1) {
+ err = errno;
+ status = EXIT_FAILURE;
+ fprintf(stderr, "%s: waitpid failed: %s\n", program, strerror(err));
+ } else if ( WIFEXITED(status) )
+ status = WEXITSTATUS(status);
+ else if ( WIFSIGNALED(status) )
+ status = WTERMSIG(status) + 128;
+ else
+ status = EX_OSERR; /* WTF? */
+ }
+ }
+
+ return status;
+}
+
diff --git a/tools/gengetopt/Makefile b/tools/gengetopt/Makefile
new file mode 100644
index 0000000..74e528e
--- /dev/null
+++ b/tools/gengetopt/Makefile
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licengengetopt under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gengetopt
+PKG_VERSION:=2.22.6
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=29749a48dda69277ab969c510597a14e
+
+HOST_FIXUP := autoreconf
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/gengetopt $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/gengetopt
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/gengetopt/patches/100-dependency_fix.patch b/tools/gengetopt/patches/100-dependency_fix.patch
new file mode 100644
index 0000000..69cb598
--- /dev/null
+++ b/tools/gengetopt/patches/100-dependency_fix.patch
@@ -0,0 +1,11 @@
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -51,7 +51,7 @@ libgengetopt_la_LIBADD = $(top_builddir)
+ @LTLIBOBJS@ \
+ skels/libgen.la
+
+-LDADD = $(top_builddir)/src/libgengetopt.la
++LDADD = libgengetopt.la
+
+ EXTRA_DIST = parser.h argsdef.h gengetopt.h ggos.h gm.h gnugetopt.h \
+ cmdline.c cmdline.h \
diff --git a/tools/gengetopt/patches/200-no_docs_tests.patch b/tools/gengetopt/patches/200-no_docs_tests.patch
new file mode 100644
index 0000000..d393069
--- /dev/null
+++ b/tools/gengetopt/patches/200-no_docs_tests.patch
@@ -0,0 +1,13 @@
+diff -urN gengetopt-2.22.6/Makefile.am gengetopt-2.22.6.new/Makefile.am
+--- gengetopt-2.22.6/Makefile.am 2012-11-02 06:26:54.000000000 -0700
++++ gengetopt-2.22.6.new/Makefile.am 2015-05-21 17:43:15.183083542 -0700
+@@ -18,6 +18,6 @@
+ ACLOCAL_AMFLAGS = -I m4 -I gl/m4
+
+ EXTRA_DIST = configure TODO LICENSE gl/m4/gnulib-cache.m4
+-SUBDIRS = gl src doc tests
++SUBDIRS = gl src
+
+-gengetoptdoc_DATA = ChangeLog COPYING NEWS THANKS INSTALL README LICENSE
+\ No newline at end of file
++gengetoptdoc_DATA = ChangeLog COPYING NEWS THANKS INSTALL README LICENSE
diff --git a/tools/gmp/Makefile b/tools/gmp/Makefile
new file mode 100644
index 0000000..fac05e3
--- /dev/null
+++ b/tools/gmp/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2009-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gmp
+PKG_VERSION:=5.1.3
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/gmp/
+PKG_MD5SUM:=e5fe367801ff067b923d1e6a126448aa
+
+HOST_FIXUP:=autoreconf
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport CFLAGS
+
+HOST_CONFIGURE_ARGS += \
+ --enable-static \
+ --disable-shared \
+ --disable-assembly \
+ --enable-cxx \
+ --enable-mpbsd
+
+ifeq ($(GNU_HOST_NAME),x86_64-linux-gnux32)
+HOST_CONFIGURE_ARGS += ABI=x32
+endif
+
+$(eval $(call HostBuild))
diff --git a/tools/include/byteswap.h b/tools/include/byteswap.h
new file mode 100644
index 0000000..015f097
--- /dev/null
+++ b/tools/include/byteswap.h
@@ -0,0 +1,5 @@
+#if defined(__linux__) || defined(__CYGWIN__)
+#include_next <byteswap.h>
+#else
+#include <endian.h>
+#endif
diff --git a/tools/include/elf.h b/tools/include/elf.h
new file mode 100644
index 0000000..036a176
--- /dev/null
+++ b/tools/include/elf.h
@@ -0,0 +1,3007 @@
+/* This file defines standard ELF types, structures, and macros.
+ Copyright (C) 1995-2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ELF_H
+#define _ELF_H 1
+
+/* Standard ELF types. */
+
+#include <stdint.h>
+
+/* Type for a 16-bit quantity. */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities. */
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities. */
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+/* Type of addresses. */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets. */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities. */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information. */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header. This appears at the start of every ELF file. */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf64_Half e_type; /* Object file type */
+ Elf64_Half e_machine; /* Architecture */
+ Elf64_Word e_version; /* Object file version */
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ Elf64_Word e_flags; /* Processor-specific flags */
+ Elf64_Half e_ehsize; /* ELF header size in bytes */
+ Elf64_Half e_phentsize; /* Program header table entry size */
+ Elf64_Half e_phnum; /* Program header table entry count */
+ Elf64_Half e_shentsize; /* Section header table entry size */
+ Elf64_Half e_shnum; /* Section header table entry count */
+ Elf64_Half e_shstrndx; /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array. The EI_* macros are indices into the
+ array. The macros under each EI_* macro are the values the byte
+ may have. */
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7f /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word. */
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+#define ELFCLASSNUM 3
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+#define ELFDATANUM 3
+
+#define EI_VERSION 6 /* File version byte index */
+ /* Value must be EV_CURRENT */
+
+#define EI_OSABI 7 /* OS ABI identification */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_SYSV 0 /* Alias. */
+#define ELFOSABI_HPUX 1 /* HP-UX */
+#define ELFOSABI_NETBSD 2 /* NetBSD. */
+#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */
+#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */
+#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
+#define ELFOSABI_AIX 7 /* IBM AIX. */
+#define ELFOSABI_IRIX 8 /* SGI Irix. */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
+#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define EI_ABIVERSION 8 /* ABI version */
+
+#define EI_PAD 9 /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type). */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_NUM 5 /* Number of defined types */
+#define ET_LOOS 0xfe00 /* OS-specific range start */
+#define ET_HIOS 0xfeff /* OS-specific range end */
+#define ET_LOPROC 0xff00 /* Processor-specific range start */
+#define ET_HIPROC 0xffff /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture). */
+
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_TILEPRO 188 /* Tilera TILEPro */
+#define EM_TILEGX 191 /* Tilera TILE-Gx */
+#define EM_NUM 192
+
+/* If it is necessary to assign new unofficial EM_* values, please
+ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+ chances of collision with official or non-GNU unofficial values. */
+
+#define EM_ALPHA 0x9026
+
+/* Legal values for e_version (version). */
+
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+#define EV_NUM 2
+
+/* Section header. */
+
+typedef struct
+{
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf64_Word sh_name; /* Section name (string tbl index) */
+ Elf64_Word sh_type; /* Section type */
+ Elf64_Xword sh_flags; /* Section flags */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Xword sh_size; /* Section size in bytes */
+ Elf64_Word sh_link; /* Link to another section */
+ Elf64_Word sh_info; /* Additional section information */
+ Elf64_Xword sh_addralign; /* Section alignment */
+ Elf64_Xword sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices. */
+
+#define SHN_UNDEF 0 /* Undefined section */
+#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
+#define SHN_LOPROC 0xff00 /* Start of processor-specific */
+#define SHN_BEFORE 0xff00 /* Order section before all others
+ (Solaris). */
+#define SHN_AFTER 0xff01 /* Order section after all others
+ (Solaris). */
+#define SHN_HIPROC 0xff1f /* End of processor-specific */
+#define SHN_LOOS 0xff20 /* Start of OS-specific */
+#define SHN_HIOS 0xff3f /* End of OS-specific */
+#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
+#define SHN_COMMON 0xfff2 /* Associated symbol is common */
+#define SHN_XINDEX 0xffff /* Index is in extra table. */
+#define SHN_HIRESERVE 0xffff /* End of reserved indices */
+
+/* Legal values for sh_type (section type). */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program data */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Notes */
+#define SHT_NOBITS 8 /* Program space with no data (bss) */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY 14 /* Array of constructors */
+#define SHT_FINI_ARRAY 15 /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
+#define SHT_GROUP 17 /* Section group */
+#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
+#define SHT_NUM 19 /* Number of defined types. */
+#define SHT_LOOS 0x60000000 /* Start OS-specific. */
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
+#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
+#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
+#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
+#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
+#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
+#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
+#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
+#define SHT_HIOS 0x6fffffff /* End OS-specific type */
+#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
+#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
+#define SHT_LOUSER 0x80000000 /* Start of application-specific */
+#define SHT_HIUSER 0x8fffffff /* End of application-specific */
+
+/* Legal values for sh_flags (section flags). */
+
+#define SHF_WRITE (1 << 0) /* Writable */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable */
+#define SHF_MERGE (1 << 4) /* Might be merged */
+#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
+#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
+ required */
+#define SHF_GROUP (1 << 9) /* Section is member of a group. */
+#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
+#define SHF_ORDERED (1 << 30) /* Special ordering requirement
+ (Solaris). */
+#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
+ referenced or allocated (Solaris).*/
+
+/* Section group handling. */
+#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
+
+/* Symbol table entry. */
+
+typedef struct
+{
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+ Elf64_Word st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf64_Section st_shndx; /* Section index */
+ Elf64_Addr st_value; /* Symbol value */
+ Elf64_Xword st_size; /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+ every dynamic symbol. */
+
+typedef struct
+{
+ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf32_Half si_flags; /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf64_Half si_flags; /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto. */
+#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags. */
+#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
+ loaded */
+/* Syminfo version values. */
+#define SYMINFO_NONE 0
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+
+/* How to extract and insert information held in the st_info field. */
+
+#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val) ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
+#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding). */
+
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* Weak symbol */
+#define STB_NUM 3 /* Number of defined types. */
+#define STB_LOOS 10 /* Start of OS-specific */
+#define STB_GNU_UNIQUE 10 /* Unique symbol. */
+#define STB_HIOS 12 /* End of OS-specific */
+#define STB_LOPROC 13 /* Start of processor-specific */
+#define STB_HIPROC 15 /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol's name is file name */
+#define STT_COMMON 5 /* Symbol is a common data object */
+#define STT_TLS 6 /* Symbol is thread-local data object*/
+#define STT_NUM 7 /* Number of defined types. */
+#define STT_LOOS 10 /* Start of OS-specific */
+#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */
+#define STT_HIOS 12 /* End of OS-specific */
+#define STT_LOPROC 13 /* Start of processor-specific */
+#define STT_HIPROC 15 /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+ of a symbol hash table section. This special index value indicates
+ the end of a chain, meaning no further symbols are found in that bucket. */
+
+#define STN_UNDEF 0 /* End of a chain. */
+
+
+/* How to extract and insert information held in the st_other field. */
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+
+/* For ELF64 the definitions are the same. */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field. */
+#define STV_DEFAULT 0 /* Default symbol visibility rules */
+#define STV_INTERNAL 1 /* Processor specific hidden class */
+#define STV_HIDDEN 2 /* Sym unavailable in other modules */
+#define STV_PROTECTED 3 /* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+ Elf64_Rela structures, so we'll leave them out until Novell (or
+ whoever) gets their act together. */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+ Elf32_Sword r_addend; /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field. */
+
+#define ELF32_R_SYM(val) ((val) >> 8)
+#define ELF32_R_TYPE(val) ((val) & 0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header. */
+
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+ Elf64_Word p_type; /* Segment type */
+ Elf64_Word p_flags; /* Segment flags */
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Xword p_filesz; /* Segment size in file */
+ Elf64_Xword p_memsz; /* Segment size in memory */
+ Elf64_Xword p_align; /* Segment alignment */
+} Elf64_Phdr;
+
+/* Special value for e_phnum. This indicates that the real number of
+ program headers is too large to fit into e_phnum. Instead the real
+ value is in the field sh_info of section 0. */
+
+#define PN_XNUM 0xffff
+
+/* Legal values for p_type (segment type). */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_TLS 7 /* Thread-local storage segment */
+#define PT_NUM 8 /* Number of defined types */
+#define PT_LOOS 0x60000000 /* Start of OS-specific */
+#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* End of OS-specific */
+#define PT_LOPROC 0x70000000 /* Start of processor-specific */
+#define PT_HIPROC 0x7fffffff /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags). */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKOS 0x0ff00000 /* OS-specific */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+#define NT_PRXREG 4 /* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
+#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV 6 /* Contains copy of auxv array */
+#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
+#define NT_ASRS 8 /* Contains copy of asrset struct */
+#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
+#define NT_PSINFO 13 /* Contains copy of psinfo struct */
+#define NT_PRCRED 14 /* Contains copy of prcred struct */
+#define NT_UTSNAME 15 /* Contains copy of utsname struct */
+#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */
+#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
+#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
+#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
+#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
+
+/* Legal values for the note segment descriptor types for object files. */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+
+/* Dynamic section entry. */
+
+typedef struct
+{
+ Elf32_Sword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf32_Word d_val; /* Integer value */
+ Elf32_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type). */
+
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_NEEDED 1 /* Name of needed library */
+#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
+#define DT_PLTGOT 3 /* Processor defined value */
+#define DT_HASH 4 /* Address of symbol hash table */
+#define DT_STRTAB 5 /* Address of string table */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+#define DT_STRSZ 10 /* Size of string table */
+#define DT_SYMENT 11 /* Size of one symbol table entry */
+#define DT_INIT 12 /* Address of init function */
+#define DT_FINI 13 /* Address of termination function */
+#define DT_SONAME 14 /* Name of shared object */
+#define DT_RPATH 15 /* Library search path (deprecated) */
+#define DT_SYMBOLIC 16 /* Start symbol search here */
+#define DT_REL 17 /* Address of Rel relocs */
+#define DT_RELSZ 18 /* Total size of Rel relocs */
+#define DT_RELENT 19 /* Size of one Rel reloc */
+#define DT_PLTREL 20 /* Type of reloc in PLT */
+#define DT_DEBUG 21 /* For debugging; unspecified */
+#define DT_TEXTREL 22 /* Reloc might modify .text */
+#define DT_JMPREL 23 /* Address of PLT relocs */
+#define DT_BIND_NOW 24 /* Process relocations of object */
+#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
+#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH 29 /* Library search path */
+#define DT_FLAGS 30 /* Flags for the object being loaded */
+#define DT_ENCODING 32 /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
+#define DT_NUM 34 /* Number used */
+#define DT_LOOS 0x6000000d /* Start of OS-specific */
+#define DT_HIOS 0x6ffff000 /* End of OS-specific */
+#define DT_LOPROC 0x70000000 /* Start of processor-specific */
+#define DT_HIPROC 0x7fffffff /* End of processor-specific */
+#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
+ approach. */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
+#define DT_CHECKSUM 0x6ffffdf8
+#define DT_PLTPADSZ 0x6ffffdf9
+#define DT_MOVEENT 0x6ffffdfa
+#define DT_MOVESZ 0x6ffffdfb
+#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
+#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
+ the following DT_* entry. */
+#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
+#define DT_VALRNGHI 0x6ffffdff
+#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+ If any adjustment is made to the ELF object after it has been
+ built these entries will need to be adjusted. */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
+#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
+#define DT_CONFIG 0x6ffffefa /* Configuration information. */
+#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
+#define DT_AUDIT 0x6ffffefc /* Object auditing. */
+#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
+#define DT_MOVETAB 0x6ffffefe /* Move table. */
+#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
+#define DT_ADDRRNGHI 0x6ffffeff
+#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
+#define DT_ADDRNUM 11
+
+/* The versioning entry types. The next are defined as part of the
+ GNU extension. */
+#define DT_VERSYM 0x6ffffff0
+
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+
+/* These were chosen by Sun. */
+#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
+#define DT_VERDEF 0x6ffffffc /* Address of version definition
+ table */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
+#define DT_VERNEED 0x6ffffffe /* Address of table with needed
+ versions */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+ range. Be compatible. */
+#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
+#define DT_FILTER 0x7fffffff /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM 3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry. */
+#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
+#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
+#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
+#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+ entry in the dynamic section. */
+#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
+#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
+#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
+#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
+#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
+#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
+#define DF_1_TRANS 0x00000200
+#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
+#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
+#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */
+#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */
+#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */
+#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */
+
+/* Flags for the feature selection in DT_FEATURE_1. */
+#define DTF_1_PARINIT 0x00000001
+#define DTF_1_CONFEXP 0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
+#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
+#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
+ generally available. */
+
+/* Version definition sections. */
+
+typedef struct
+{
+ Elf32_Half vd_version; /* Version revision */
+ Elf32_Half vd_flags; /* Version information */
+ Elf32_Half vd_ndx; /* Version Index */
+ Elf32_Half vd_cnt; /* Number of associated aux entries */
+ Elf32_Word vd_hash; /* Version name hash value */
+ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf32_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+ Elf64_Half vd_version; /* Version revision */
+ Elf64_Half vd_flags; /* Version information */
+ Elf64_Half vd_ndx; /* Version Index */
+ Elf64_Half vd_cnt; /* Number of associated aux entries */
+ Elf64_Word vd_hash; /* Version name hash value */
+ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf64_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision). */
+#define VER_DEF_NONE 0 /* No version */
+#define VER_DEF_CURRENT 1 /* Current version */
+#define VER_DEF_NUM 2 /* Given version number */
+
+/* Legal values for vd_flags (version information flags). */
+#define VER_FLG_BASE 0x1 /* Version definition of file itself */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+/* Versym symbol index values. */
+#define VER_NDX_LOCAL 0 /* Symbol is local. */
+#define VER_NDX_GLOBAL 1 /* Symbol is global. */
+#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
+#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
+
+/* Auxialiary version information. */
+
+typedef struct
+{
+ Elf32_Word vda_name; /* Version or dependency names */
+ Elf32_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+ Elf64_Word vda_name; /* Version or dependency names */
+ Elf64_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section. */
+
+typedef struct
+{
+ Elf32_Half vn_version; /* Version of structure */
+ Elf32_Half vn_cnt; /* Number of associated aux entries */
+ Elf32_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf32_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+ Elf64_Half vn_version; /* Version of structure */
+ Elf64_Half vn_cnt; /* Number of associated aux entries */
+ Elf64_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf64_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision). */
+#define VER_NEED_NONE 0 /* No version */
+#define VER_NEED_CURRENT 1 /* Current version */
+#define VER_NEED_NUM 2 /* Given version number */
+
+/* Auxiliary needed version information. */
+
+typedef struct
+{
+ Elf32_Word vna_hash; /* Hash value of dependency name */
+ Elf32_Half vna_flags; /* Dependency specific information */
+ Elf32_Half vna_other; /* Unused */
+ Elf32_Word vna_name; /* Dependency name string offset */
+ Elf32_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+ Elf64_Word vna_hash; /* Hash value of dependency name */
+ Elf64_Half vna_flags; /* Dependency specific information */
+ Elf64_Half vna_other; /* Unused */
+ Elf64_Word vna_name; /* Dependency name string offset */
+ Elf64_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags. */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+
+/* Auxiliary vector. */
+
+/* This vector is normally only used by the program interpreter. The
+ usual definition in an ABI supplement uses the name auxv_t. The
+ vector is not usually defined in a standard <elf.h> file, but it
+ can't hurt. We rename it to avoid conflicts. The sizes of these
+ types are an arrangement between the exec server and the program
+ interpreter, so we don't fully specify them here. */
+
+typedef struct
+{
+ uint32_t a_type; /* Entry type */
+ union
+ {
+ uint32_t a_val; /* Integer value */
+ /* We use to have pointer elements added here. We cannot do that,
+ though, since it does not work when using 32-bit definitions
+ on 64-bit platforms and vice versa. */
+ } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+ uint64_t a_type; /* Entry type */
+ union
+ {
+ uint64_t a_val; /* Integer value */
+ /* We use to have pointer elements added here. We cannot do that,
+ though, since it does not work when using 32-bit definitions
+ on 64-bit platforms and vice versa. */
+ } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type). */
+
+#define AT_NULL 0 /* End of vector */
+#define AT_IGNORE 1 /* Entry should be ignored */
+#define AT_EXECFD 2 /* File descriptor of program */
+#define AT_PHDR 3 /* Program headers for program */
+#define AT_PHENT 4 /* Size of program header entry */
+#define AT_PHNUM 5 /* Number of program headers */
+#define AT_PAGESZ 6 /* System page size */
+#define AT_BASE 7 /* Base address of interpreter */
+#define AT_FLAGS 8 /* Flags */
+#define AT_ENTRY 9 /* Entry point of program */
+#define AT_NOTELF 10 /* Program is not ELF */
+#define AT_UID 11 /* Real uid */
+#define AT_EUID 12 /* Effective uid */
+#define AT_GID 13 /* Real gid */
+#define AT_EGID 14 /* Effective gid */
+#define AT_CLKTCK 17 /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware. */
+#define AT_PLATFORM 15 /* String identifying platform. */
+#define AT_HWCAP 16 /* Machine dependent hints about
+ processor capabilities. */
+
+/* This entry gives some information about the FPU initialization
+ performed by the kernel. */
+#define AT_FPUCW 18 /* Used FPU control word. */
+
+/* Cache block sizes. */
+#define AT_DCACHEBSIZE 19 /* Data cache block size. */
+#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */
+#define AT_UCACHEBSIZE 21 /* Unified cache block size. */
+
+/* A special ignored value for PPC, used by the kernel to control the
+ interpretation of the AUXV. Must be > 16. */
+#define AT_IGNOREPPC 22 /* Entry should be ignored. */
+
+#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
+
+#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/
+
+#define AT_RANDOM 25 /* Address of 16 random bytes. */
+
+#define AT_EXECFN 31 /* Filename of executable. */
+
+/* Pointer to the global system page used for system calls and other
+ nice things. */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
+ log2 of line size; mask those to get cache size. */
+#define AT_L1I_CACHESHAPE 34
+#define AT_L1D_CACHESHAPE 35
+#define AT_L2_CACHESHAPE 36
+#define AT_L3_CACHESHAPE 37
+
+/* Note section contents. Each entry in the note section begins with
+ a header of a fixed form. */
+
+typedef struct
+{
+ Elf32_Word n_namesz; /* Length of the note's name. */
+ Elf32_Word n_descsz; /* Length of the note's descriptor. */
+ Elf32_Word n_type; /* Type of the note. */
+} Elf32_Nhdr;
+
+typedef struct
+{
+ Elf64_Word n_namesz; /* Length of the note's name. */
+ Elf64_Word n_descsz; /* Length of the note's descriptor. */
+ Elf64_Word n_type; /* Type of the note. */
+} Elf64_Nhdr;
+
+/* Known names of notes. */
+
+/* Solaris entries in the note section have this name. */
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+
+/* Note entries for GNU systems have this name. */
+#define ELF_NOTE_GNU "GNU"
+
+
+/* Defined types of notes for Solaris. */
+
+/* Value of descriptor (one word) is desired pagesize for the binary. */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+/* Defined note types for GNU systems. */
+
+/* ABI information. The descriptor consists of words:
+ word 0: OS descriptor
+ word 1: major version of the ABI
+ word 2: minor version of the ABI
+ word 3: subminor version of the ABI
+*/
+#define NT_GNU_ABI_TAG 1
+#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */
+
+/* Known OSes. These values can appear in word 0 of an
+ NT_GNU_ABI_TAG note section entry. */
+#define ELF_NOTE_OS_LINUX 0
+#define ELF_NOTE_OS_GNU 1
+#define ELF_NOTE_OS_SOLARIS2 2
+#define ELF_NOTE_OS_FREEBSD 3
+
+/* Synthetic hwcap information. The descriptor begins with two words:
+ word 0: number of entries
+ word 1: bitmask of enabled entries
+ Then follow variable-length entries, one byte followed by a
+ '\0'-terminated hwcap name string. The byte gives the bit
+ number to test if enabled, (1U << bit) & bitmask. */
+#define NT_GNU_HWCAP 2
+
+/* Build ID bits as generated by ld --build-id.
+ The descriptor consists of any nonzero number of bytes. */
+#define NT_GNU_BUILD_ID 3
+
+/* Version note generated by GNU gold containing a version string. */
+#define NT_GNU_GOLD_VERSION 4
+
+
+/* Move records. */
+typedef struct
+{
+ Elf32_Xword m_value; /* Symbol value. */
+ Elf32_Word m_info; /* Size and index. */
+ Elf32_Word m_poffset; /* Symbol offset. */
+ Elf32_Half m_repeat; /* Repeat count. */
+ Elf32_Half m_stride; /* Stride info. */
+} Elf32_Move;
+
+typedef struct
+{
+ Elf64_Xword m_value; /* Symbol value. */
+ Elf64_Xword m_info; /* Size and index. */
+ Elf64_Xword m_poffset; /* Symbol offset. */
+ Elf64_Half m_repeat; /* Repeat count. */
+ Elf64_Half m_stride; /* Stride info. */
+} Elf64_Move;
+
+/* Macro to construct move records. */
+#define ELF32_M_SYM(info) ((info) >> 8)
+#define ELF32_M_SIZE(info) ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info) ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions. */
+
+/* Values for Elf32_Ehdr.e_flags. */
+#define EF_CPU32 0x00810000
+
+/* m68k relocs. */
+
+#define R_68K_NONE 0 /* No reloc */
+#define R_68K_32 1 /* Direct 32 bit */
+#define R_68K_16 2 /* Direct 16 bit */
+#define R_68K_8 3 /* Direct 8 bit */
+#define R_68K_PC32 4 /* PC relative 32 bit */
+#define R_68K_PC16 5 /* PC relative 16 bit */
+#define R_68K_PC8 6 /* PC relative 8 bit */
+#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
+#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
+#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O 10 /* 32 bit GOT offset */
+#define R_68K_GOT16O 11 /* 16 bit GOT offset */
+#define R_68K_GOT8O 12 /* 8 bit GOT offset */
+#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
+#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
+#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
+#define R_68K_PLT32O 16 /* 32 bit PLT offset */
+#define R_68K_PLT16O 17 /* 16 bit PLT offset */
+#define R_68K_PLT8O 18 /* 8 bit PLT offset */
+#define R_68K_COPY 19 /* Copy symbol at runtime */
+#define R_68K_GLOB_DAT 20 /* Create GOT entry */
+#define R_68K_JMP_SLOT 21 /* Create PLT entry */
+#define R_68K_RELATIVE 22 /* Adjust by program base */
+#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */
+#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */
+#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */
+#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */
+#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */
+#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */
+#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */
+#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */
+#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */
+#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */
+#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */
+#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */
+#define R_68K_TLS_LE32 37 /* 32 bit offset relative to
+ static TLS block */
+#define R_68K_TLS_LE16 38 /* 16 bit offset relative to
+ static TLS block */
+#define R_68K_TLS_LE8 39 /* 8 bit offset relative to
+ static TLS block */
+#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */
+#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */
+#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */
+/* Keep this the last entry. */
+#define R_68K_NUM 43
+
+/* Intel 80386 specific definitions. */
+
+/* i386 relocs. */
+
+#define R_386_NONE 0 /* No reloc */
+#define R_386_32 1 /* Direct 32 bit */
+#define R_386_PC32 2 /* PC relative 32 bit */
+#define R_386_GOT32 3 /* 32 bit GOT entry */
+#define R_386_PLT32 4 /* 32 bit PLT address */
+#define R_386_COPY 5 /* Copy symbol at runtime */
+#define R_386_GLOB_DAT 6 /* Create GOT entry */
+#define R_386_JMP_SLOT 7 /* Create PLT entry */
+#define R_386_RELATIVE 8 /* Adjust by program base */
+#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
+#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
+#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
+ block offset */
+#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block
+ offset */
+#define R_386_TLS_LE 17 /* Offset relative to static TLS
+ block */
+#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of
+ general dynamic thread local data */
+#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of
+ local dynamic thread local data
+ in LE code */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic
+ thread local data */
+#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL 26 /* Relocation for call to
+ __tls_get_addr() */
+#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic
+ thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30 /* Relocation for call to
+ __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
+#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS
+ block offset */
+#define R_386_TLS_LE_32 34 /* Negated offset relative to static
+ TLS block */
+#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
+#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
+/* 38? */
+#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */
+#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS
+ descriptor for
+ relaxation. */
+#define R_386_TLS_DESC 41 /* TLS descriptor containing
+ pointer to code and to
+ argument, returning the TLS
+ offset for the symbol. */
+#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */
+/* Keep this the last entry. */
+#define R_386_NUM 43
+
+/* SUN SPARC specific definitions. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags. */
+
+#define EF_SPARCV9_MM 3
+#define EF_SPARCV9_TSO 0
+#define EF_SPARCV9_PSO 1
+#define EF_SPARCV9_RMO 2
+#define EF_SPARC_LEDATA 0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK 0xFFFF00
+#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs. */
+
+#define R_SPARC_NONE 0 /* No reloc */
+#define R_SPARC_8 1 /* Direct 8 bit */
+#define R_SPARC_16 2 /* Direct 16 bit */
+#define R_SPARC_32 3 /* Direct 32 bit */
+#define R_SPARC_DISP8 4 /* PC relative 8 bit */
+#define R_SPARC_DISP16 5 /* PC relative 16 bit */
+#define R_SPARC_DISP32 6 /* PC relative 32 bit */
+#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
+#define R_SPARC_HI22 9 /* High 22 bit */
+#define R_SPARC_22 10 /* Direct 22 bit */
+#define R_SPARC_13 11 /* Direct 13 bit */
+#define R_SPARC_LO10 12 /* Truncated 10 bit */
+#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
+#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
+#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
+#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
+#define R_SPARC_COPY 19 /* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
+#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
+#define R_SPARC_RELATIVE 22 /* Adjust by program base */
+#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs. */
+
+#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10 30 /* Direct 10 bit */
+#define R_SPARC_11 31 /* Direct 11 bit */
+#define R_SPARC_64 32 /* Direct 64 bit */
+#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10 35 /* High middle 10 bits of ... */
+#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
+#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */
+#define R_SPARC_7 43 /* Direct 7 bit */
+#define R_SPARC_5 44 /* Direct 5 bit */
+#define R_SPARC_6 45 /* Direct 6 bit */
+#define R_SPARC_DISP64 46 /* PC relative 64 bit */
+#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22 48 /* High 22 bit complemented */
+#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
+#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
+#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
+#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER 53 /* Global register usage */
+#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
+#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+#define R_SPARC_GOTDATA_HIX22 80
+#define R_SPARC_GOTDATA_LOX10 81
+#define R_SPARC_GOTDATA_OP_HIX22 82
+#define R_SPARC_GOTDATA_OP_LOX10 83
+#define R_SPARC_GOTDATA_OP 84
+#define R_SPARC_H34 85
+#define R_SPARC_SIZE32 86
+#define R_SPARC_SIZE64 87
+#define R_SPARC_WDISP10 88
+#define R_SPARC_JMP_IREL 248
+#define R_SPARC_IRELATIVE 249
+#define R_SPARC_GNU_VTINHERIT 250
+#define R_SPARC_GNU_VTENTRY 251
+#define R_SPARC_REV32 252
+/* Keep this the last entry. */
+#define R_SPARC_NUM 253
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM 2
+
+/* MIPS R3000 specific definitions. */
+
+/* Legal values for e_flags field of Elf32_Ehdr. */
+
+#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
+#define EF_MIPS_PIC 2 /* Contains PIC code */
+#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
+#define EF_MIPS_XGOT 8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2 32
+#define EF_MIPS_ABI_ON32 64
+#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
+
+/* Legal values for MIPS architecture level. */
+
+#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
+#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
+#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
+#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
+
+/* The following are non-official names and should not be used. */
+
+#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
+#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
+#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
+#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
+
+/* Special section indices. */
+
+#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
+#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
+#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
+#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
+#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
+#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
+#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
+#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
+#define SHT_MIPS_SHDR 0x70000010
+#define SHT_MIPS_FDESC 0x70000011
+#define SHT_MIPS_EXTSYM 0x70000012
+#define SHT_MIPS_DENSE 0x70000013
+#define SHT_MIPS_PDESC 0x70000014
+#define SHT_MIPS_LOCSYM 0x70000015
+#define SHT_MIPS_AUXSYM 0x70000016
+#define SHT_MIPS_OPTSYM 0x70000017
+#define SHT_MIPS_LOCSTR 0x70000018
+#define SHT_MIPS_LINE 0x70000019
+#define SHT_MIPS_RFDESC 0x7000001a
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
+#define SHF_MIPS_MERGE 0x20000000
+#define SHF_MIPS_ADDR 0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL 0x04000000
+#define SHF_MIPS_NAMES 0x02000000
+#define SHF_MIPS_NODUPE 0x01000000
+
+
+/* Symbol tables. */
+
+/* MIPS specific values for `st_other'. */
+#define STO_MIPS_DEFAULT 0x0
+#define STO_MIPS_INTERNAL 0x1
+#define STO_MIPS_HIDDEN 0x2
+#define STO_MIPS_PROTECTED 0x3
+#define STO_MIPS_PLT 0x8
+#define STO_MIPS_SC_ALIGN_UNUSED 0xff
+
+/* MIPS specific values for `st_info'. */
+#define STB_MIPS_SPLIT_COMMON 13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB. */
+
+typedef union
+{
+ struct
+ {
+ Elf32_Word gt_current_g_value; /* -G value used for compilation */
+ Elf32_Word gt_unused; /* Not used */
+ } gt_header; /* First entry in section */
+ struct
+ {
+ Elf32_Word gt_g_value; /* If this value were used for -G */
+ Elf32_Word gt_bytes; /* This many bytes would be used */
+ } gt_entry; /* Subsequent entries in section */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO. */
+
+typedef struct
+{
+ Elf32_Word ri_gprmask; /* General registers used */
+ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
+ Elf32_Sword ri_gp_value; /* $gp register value */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS. */
+
+typedef struct
+{
+ unsigned char kind; /* Determines interpretation of the
+ variable part of descriptor. */
+ unsigned char size; /* Size of descriptor, including header. */
+ Elf32_Section section; /* Section header index of section affected,
+ 0 for global options. */
+ Elf32_Word info; /* Kind-specific information. */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options. */
+
+#define ODK_NULL 0 /* Undefined. */
+#define ODK_REGINFO 1 /* Register usage information. */
+#define ODK_EXCEPTIONS 2 /* Exception processing options. */
+#define ODK_PAD 3 /* Section padding options. */
+#define ODK_HWPATCH 4 /* Hardware workarounds performed */
+#define ODK_FILL 5 /* record the fill value used by the linker. */
+#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
+#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
+#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
+
+#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
+#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
+#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
+#define OEX_SMM 0x20000 /* Force sequential memory mode? */
+#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
+#define OEX_PRECISEFP OEX_FPDBUG
+#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
+
+#define OEX_FPU_INVAL 0x10
+#define OEX_FPU_DIV0 0x08
+#define OEX_FPU_OFLO 0x04
+#define OEX_FPU_UFLO 0x02
+#define OEX_FPU_INEX 0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
+
+#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
+#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
+#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
+#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
+
+#define OPAD_PREFIX 0x1
+#define OPAD_POSTFIX 0x2
+#define OPAD_SYMBOL 0x4
+
+/* Entry found in `.options' section. */
+
+typedef struct
+{
+ Elf32_Word hwp_flags1; /* Extra flags. */
+ Elf32_Word hwp_flags2; /* Extra flags. */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
+
+#define OHWA0_R4KEOP_CHECKED 0x00000001
+#define OHWA1_R4KEOP_CLEAN 0x00000002
+
+/* MIPS relocs. */
+
+#define R_MIPS_NONE 0 /* No reloc */
+#define R_MIPS_16 1 /* Direct 16 bit */
+#define R_MIPS_32 2 /* Direct 32 bit */
+#define R_MIPS_REL32 3 /* PC relative 32 bit */
+#define R_MIPS_26 4 /* Direct 26 bit shifted */
+#define R_MIPS_HI16 5 /* High 16 bit */
+#define R_MIPS_LO16 6 /* Low 16 bit */
+#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
+#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
+#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
+#define R_MIPS_PC16 10 /* PC relative 16 bit */
+#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_RELGOT 36
+#define R_MIPS_JALR 37
+#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */
+#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */
+#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */
+#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */
+#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */
+#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */
+#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */
+#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */
+#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */
+#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */
+#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
+#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
+#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
+#define R_MIPS_GLOB_DAT 51
+#define R_MIPS_COPY 126
+#define R_MIPS_JUMP_SLOT 127
+/* Keep this the last entry. */
+#define R_MIPS_NUM 128
+
+/* Legal values for p_type field of Elf32_Phdr. */
+
+#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
+#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+
+/* Special program header types. */
+
+#define PF_MIPS_LOCAL 0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn. */
+
+#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
+#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
+#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS 0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
+#define DT_MIPS_MSYM 0x70000007
+#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
+#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
+#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
+#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in
+ DT_MIPS_DELTA_CLASS. */
+#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+ DT_MIPS_DELTA_INSTANCE. */
+#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+ DT_MIPS_DELTA_RELOC. */
+#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta
+ relocations refer to. */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+ DT_MIPS_DELTA_SYM. */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+ class declaration. */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+ DT_MIPS_DELTA_CLASSSYM. */
+#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
+#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+ function stored in GOT. */
+#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
+ by rld on dlopen() calls. */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
+#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
+/* The address of .got.plt in an executable using the new non-PIC ABI. */
+#define DT_MIPS_PLTGOT 0x70000032
+/* The base of the PLT in an executable using the new non-PIC ABI if that
+ PLT is writable. For a non-writable PLT, this is omitted or has a zero
+ value. */
+#define DT_MIPS_RWPLT 0x70000034
+#define DT_MIPS_NUM 0x35
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
+
+#define RHF_NONE 0 /* No flags */
+#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
+#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE (1 << 3)
+#define RHF_SGI_ONLY (1 << 4)
+#define RHF_GUARANTEE_INIT (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
+#define RHF_GUARANTEE_START_INIT (1 << 7)
+#define RHF_PIXIE (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
+#define RHF_REQUICKSTART (1 << 10)
+#define RHF_REQUICKSTARTED (1 << 11)
+#define RHF_CORD (1 << 12)
+#define RHF_NO_UNRES_UNDEF (1 << 13)
+#define RHF_RLD_ORDER_SAFE (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST. */
+
+typedef struct
+{
+ Elf32_Word l_name; /* Name (string table index) */
+ Elf32_Word l_time_stamp; /* Timestamp */
+ Elf32_Word l_checksum; /* Checksum */
+ Elf32_Word l_version; /* Interface version */
+ Elf32_Word l_flags; /* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+ Elf64_Word l_name; /* Name (string table index) */
+ Elf64_Word l_time_stamp; /* Timestamp */
+ Elf64_Word l_checksum; /* Checksum */
+ Elf64_Word l_version; /* Interface version */
+ Elf64_Word l_flags; /* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags. */
+
+#define LL_NONE 0
+#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
+#define LL_REQUIRE_MINOR (1 << 2)
+#define LL_EXPORTS (1 << 3)
+#define LL_DELAY_LOAD (1 << 4)
+#define LL_DELTA (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT. */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+/* HPPA specific definitions. */
+
+/* Legal values for e_flags field of Elf32_Ehdr. */
+
+#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */
+#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */
+#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch
+ prediction. */
+#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */
+#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are: */
+
+#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */
+#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */
+#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */
+
+/* Additional section indeces. */
+
+#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared
+ symbols in ANSI C. */
+#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */
+#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */
+#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
+
+#define STT_HP_OPAQUE (STT_LOOS + 0x1)
+#define STT_HP_STUB (STT_LOOS + 0x2)
+
+/* HPPA relocs. */
+
+#define R_PARISC_NONE 0 /* No reloc. */
+#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
+#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
+#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
+#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */
+#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */
+#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */
+#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */
+#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */
+#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */
+#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */
+#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */
+#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */
+#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */
+#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */
+#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */
+#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */
+#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */
+#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */
+#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */
+#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */
+#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */
+#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64 64 /* 64 bits function address. */
+#define R_PARISC_PLABEL32 65 /* 32 bits function address. */
+#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */
+#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */
+#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */
+#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */
+#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */
+#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */
+#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */
+#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */
+#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */
+#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */
+#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */
+#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */
+#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */
+#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */
+#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */
+#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */
+#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */
+#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */
+#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */
+#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */
+#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */
+#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */
+#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */
+#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */
+#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */
+#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */
+#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */
+#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */
+#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */
+#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */
+#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */
+#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */
+#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LORESERVE 128
+#define R_PARISC_COPY 128 /* Copy relocation. */
+#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */
+#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */
+#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */
+#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */
+#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */
+#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */
+#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */
+#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_GNU_VTENTRY 232
+#define R_PARISC_GNU_VTINHERIT 233
+#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */
+#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */
+#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */
+#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */
+#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */
+#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */
+#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */
+#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */
+#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */
+#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */
+#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */
+#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */
+#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L
+#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R
+#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L
+#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R
+#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32
+#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64
+#define R_PARISC_HIRESERVE 255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
+
+#define PT_HP_TLS (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
+#define PT_HP_STACK (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT 0x70000000
+#define PT_PARISC_UNWIND 0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */
+
+#define PF_PARISC_SBP 0x08000000
+
+#define PF_HP_PAGE_SIZE 0x00100000
+#define PF_HP_FAR_SHARED 0x00200000
+#define PF_HP_NEAR_SHARED 0x00400000
+#define PF_HP_CODE 0x01000000
+#define PF_HP_MODIFY 0x02000000
+#define PF_HP_LAZYSWAP 0x04000000
+#define PF_HP_SBP 0x08000000
+
+
+/* Alpha specific definitions. */
+
+/* Legal values for e_flags field of Elf64_Ehdr. */
+
+#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
+#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
+
+/* Legal values for sh_type field of Elf64_Shdr. */
+
+/* These two are primerily concerned with ECOFF debugging info. */
+#define SHT_ALPHA_DEBUG 0x70000001
+#define SHT_ALPHA_REGINFO 0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr. */
+
+#define SHF_ALPHA_GPREL 0x10000000
+
+/* Legal values for st_other field of Elf64_Sym. */
+#define STO_ALPHA_NOPV 0x80 /* No PV required. */
+#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
+
+/* Alpha relocs. */
+
+#define R_ALPHA_NONE 0 /* No reloc */
+#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
+#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
+#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
+#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
+#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
+#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
+#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */
+#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
+#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI 28
+#define R_ALPHA_TLSGD 29
+#define R_ALPHA_TLS_LDM 30
+#define R_ALPHA_DTPMOD64 31
+#define R_ALPHA_GOTDTPREL 32
+#define R_ALPHA_DTPREL64 33
+#define R_ALPHA_DTPRELHI 34
+#define R_ALPHA_DTPRELLO 35
+#define R_ALPHA_DTPREL16 36
+#define R_ALPHA_GOTTPREL 37
+#define R_ALPHA_TPREL64 38
+#define R_ALPHA_TPRELHI 39
+#define R_ALPHA_TPRELLO 40
+#define R_ALPHA_TPREL16 41
+/* Keep this the last entry. */
+#define R_ALPHA_NUM 46
+
+/* Magic values of the LITUSE relocation addend. */
+#define LITUSE_ALPHA_ADDR 0
+#define LITUSE_ALPHA_BASE 1
+#define LITUSE_ALPHA_BYTOFF 2
+#define LITUSE_ALPHA_JSR 3
+#define LITUSE_ALPHA_TLS_GD 4
+#define LITUSE_ALPHA_TLS_LDM 5
+
+/* Legal values for d_tag of Elf64_Dyn. */
+#define DT_ALPHA_PLTRO (DT_LOPROC + 0)
+#define DT_ALPHA_NUM 1
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags. */
+#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib
+ flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1 /* 32bit absolute address */
+#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+#define R_PPC_ADDR16 3 /* 16bit absolute address */
+#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10 /* PC relative 26 bit */
+#define R_PPC_REL14 11 /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+ in the SVR4 ELF ABI. */
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
+
+/* Diab tool relocations. */
+#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
+
+/* GNU extension to support local ifunc. */
+#define R_PPC_IRELATIVE 248
+
+/* GNU relocs used in PIC code sequences. */
+#define R_PPC_REL16 249 /* half16 (sym+add-.) */
+#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */
+#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */
+#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+ that may still be in object files. */
+#define R_PPC_TOC16 255
+
+/* PowerPC specific values for the Dyn d_tag field. */
+#define DT_PPC_GOT (DT_LOPROC + 0)
+#define DT_PPC_NUM 1
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */
+#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */
+#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
+#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */
+#define R_PPC64_ADDR64 38 /* doubleword64 S + A */
+#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */
+#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */
+#define R_PPC64_UADDR64 43 /* doubleword64 S + A */
+#define R_PPC64_REL64 44 /* doubleword64 S + A - P */
+#define R_PPC64_PLT64 45 /* doubleword64 L + A */
+#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */
+#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */
+#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */
+#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */
+#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */
+#define R_PPC64_TOC 51 /* doubleword64 .TOC */
+#define R_PPC64_PLTGOT16 52 /* half16* M + A */
+#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */
+#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */
+#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */
+
+#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */
+#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */
+#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */
+#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */
+#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */
+#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */
+#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */
+#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */
+#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */
+#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* GNU extension to support local ifunc. */
+#define R_PPC64_JMP_IREL 247
+#define R_PPC64_IRELATIVE 248
+#define R_PPC64_REL16 249 /* half16 (sym+add-.) */
+#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */
+#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */
+#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */
+
+/* PowerPC64 specific values for the Dyn d_tag field. */
+#define DT_PPC64_GLINK (DT_LOPROC + 0)
+#define DT_PPC64_OPD (DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_NUM 3
+
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_ARM_RELEXEC 0x01
+#define EF_ARM_HASENTRY 0x02
+#define EF_ARM_INTERWORK 0x04
+#define EF_ARM_APCS_26 0x08
+#define EF_ARM_APCS_FLOAT 0x10
+#define EF_ARM_PIC 0x20
+#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI 0x80
+#define EF_ARM_OLD_ABI 0x100
+#define EF_ARM_SOFT_FLOAT 0x200
+#define EF_ARM_VFP_FLOAT 0x400
+#define EF_ARM_MAVERICK_FLOAT 0x800
+
+
+/* Other constants defined in the ARM ELF spec. version B-01. */
+/* NB. These conflict with values defined above. */
+#define EF_ARM_SYMSARESORTED 0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_EABIMASK 0XFF000000
+
+/* Constants defined in AAELF. */
+#define EF_ARM_BE8 0x00800000
+#define EF_ARM_LE8 0x00400000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+
+/* Additional symbol types for Thumb. */
+#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */
+#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
+#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
+ in the input to a link step. */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB 0x10000000 /* Segment contains the location
+ addressed by the static base. */
+#define PF_ARM_PI 0x20000000 /* Position-independent segment. */
+#define PF_ARM_ABS 0x40000000 /* Absolute segment. */
+
+/* Processor specific values for the Phdr p_type field. */
+#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */
+
+/* Processor specific values for the Shdr sh_type field. */
+#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */
+#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */
+#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */
+
+
+/* ARM relocs. */
+
+#define R_ARM_NONE 0 /* No reloc */
+#define R_ARM_PC24 1 /* PC relative 26 bit branch */
+#define R_ARM_ABS32 2 /* Direct 32 bit */
+#define R_ARM_REL32 3 /* PC relative 32 bit */
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5 /* Direct 16 bit */
+#define R_ARM_ABS12 6 /* Direct 12 bit */
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8 /* Direct 8 bit */
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13 /* Obsolete static relocation. */
+#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
+#define R_ARM_COPY 20 /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
+#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
+#define R_ARM_RELATIVE 23 /* Adjust by program base */
+#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
+#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32 26 /* 32 bit GOT entry */
+#define R_ARM_PLT32 27 /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0 32
+#define R_ARM_ALU_PCREL_15_8 33
+#define R_ARM_ALU_PCREL_23_15 34
+#define R_ARM_LDR_SBREL_11_0 35
+#define R_ARM_ALU_SBREL_19_12 36
+#define R_ARM_ALU_SBREL_27_20 37
+#define R_ARM_TLS_GOTDESC 90
+#define R_ARM_TLS_CALL 91
+#define R_ARM_TLS_DESCSEQ 92
+#define R_ARM_THM_TLS_CALL 93
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
+#define R_ARM_THM_PC9 103 /* thumb conditional branch */
+#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic
+ thread local data */
+#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic
+ thread local data */
+#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS
+ block */
+#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of
+ static TLS block offset */
+#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static
+ TLS block */
+#define R_ARM_THM_TLS_DESCSEQ 129
+#define R_ARM_IRELATIVE 160
+#define R_ARM_RXPC25 249
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS22 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+/* Keep this the last entry. */
+#define R_ARM_NUM 256
+
+/* IA-64 specific declarations. */
+
+/* Processor specific flags for the Ehdr e_flags field. */
+#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
+#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
+#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field. */
+#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
+#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
+#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
+
+/* Processor specific flags for the Phdr p_flags field. */
+#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field. */
+#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field. */
+#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
+#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field. */
+#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
+#define DT_IA_64_NUM 1
+
+/* IA-64 relocations. */
+#define R_IA64_NONE 0x00 /* none */
+#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
+#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
+#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
+#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
+#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
+#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
+#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY 0x84 /* copy relocation */
+#define R_IA64_SUB 0x85 /* Addend and symbol difference */
+#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
+#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
+#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_SH_MACH_MASK 0x1f
+#define EF_SH_UNKNOWN 0x0
+#define EF_SH1 0x1
+#define EF_SH2 0x2
+#define EF_SH3 0x3
+#define EF_SH_DSP 0x4
+#define EF_SH3_DSP 0x5
+#define EF_SH4AL_DSP 0x6
+#define EF_SH3E 0x8
+#define EF_SH4 0x9
+#define EF_SH2E 0xb
+#define EF_SH4A 0xc
+#define EF_SH2A 0xd
+#define EF_SH4_NOFPU 0x10
+#define EF_SH4A_NOFPU 0x11
+#define EF_SH4_NOMMU_NOFPU 0x12
+#define EF_SH2A_NOFPU 0x13
+#define EF_SH3_NOMMU 0x14
+#define EF_SH2A_SH4_NOFPU 0x15
+#define EF_SH2A_SH3_NOFPU 0x16
+#define EF_SH2A_SH4 0x17
+#define EF_SH2A_SH3E 0x18
+
+/* SH relocs. */
+#define R_SH_NONE 0
+#define R_SH_DIR32 1
+#define R_SH_REL32 2
+#define R_SH_DIR8WPN 3
+#define R_SH_IND12W 4
+#define R_SH_DIR8WPL 5
+#define R_SH_DIR8WPZ 6
+#define R_SH_DIR8BP 7
+#define R_SH_DIR8W 8
+#define R_SH_DIR8L 9
+#define R_SH_SWITCH16 25
+#define R_SH_SWITCH32 26
+#define R_SH_USES 27
+#define R_SH_COUNT 28
+#define R_SH_ALIGN 29
+#define R_SH_CODE 30
+#define R_SH_DATA 31
+#define R_SH_LABEL 32
+#define R_SH_SWITCH8 33
+#define R_SH_GNU_VTINHERIT 34
+#define R_SH_GNU_VTENTRY 35
+#define R_SH_TLS_GD_32 144
+#define R_SH_TLS_LD_32 145
+#define R_SH_TLS_LDO_32 146
+#define R_SH_TLS_IE_32 147
+#define R_SH_TLS_LE_32 148
+#define R_SH_TLS_DTPMOD32 149
+#define R_SH_TLS_DTPOFF32 150
+#define R_SH_TLS_TPOFF32 151
+#define R_SH_GOT32 160
+#define R_SH_PLT32 161
+#define R_SH_COPY 162
+#define R_SH_GLOB_DAT 163
+#define R_SH_JMP_SLOT 164
+#define R_SH_RELATIVE 165
+#define R_SH_GOTOFF 166
+#define R_SH_GOTPC 167
+/* Keep this the last entry. */
+#define R_SH_NUM 256
+
+/* S/390 specific definitions. */
+
+/* Valid values for the e_flags field. */
+
+#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */
+
+/* Additional s390 relocs */
+
+#define R_390_NONE 0 /* No reloc. */
+#define R_390_8 1 /* Direct 8 bit. */
+#define R_390_12 2 /* Direct 12 bit. */
+#define R_390_16 3 /* Direct 16 bit. */
+#define R_390_32 4 /* Direct 32 bit. */
+#define R_390_PC32 5 /* PC relative 32 bit. */
+#define R_390_GOT12 6 /* 12 bit GOT offset. */
+#define R_390_GOT32 7 /* 32 bit GOT offset. */
+#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
+#define R_390_COPY 9 /* Copy symbol at runtime. */
+#define R_390_GLOB_DAT 10 /* Create GOT entry. */
+#define R_390_JMP_SLOT 11 /* Create PLT entry. */
+#define R_390_RELATIVE 12 /* Adjust by program base. */
+#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */
+#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
+#define R_390_GOT16 15 /* 16 bit GOT offset. */
+#define R_390_PC16 16 /* PC relative 16 bit. */
+#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
+#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
+#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
+#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
+#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
+#define R_390_64 22 /* Direct 64 bit. */
+#define R_390_PC64 23 /* PC relative 64 bit. */
+#define R_390_GOT64 24 /* 64 bit GOT offset. */
+#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
+#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
+#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
+#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
+#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
+#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
+#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
+#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
+#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
+#define R_390_TLS_GDCALL 38 /* Tag for function call in general
+ dynamic TLS code. */
+#define R_390_TLS_LDCALL 39 /* Tag for function call in local
+ dynamic TLS code. */
+#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic
+ thread local data. */
+#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic
+ thread local data. */
+#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic
+ thread local data in LE code. */
+#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic
+ thread local data in LE code. */
+#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to
+ static TLS block. */
+#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to
+ static TLS block. */
+#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS
+ block. */
+#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS
+ block. */
+#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
+#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
+#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS
+ block. */
+#define R_390_20 57 /* Direct 20 bit. */
+#define R_390_GOT20 58 /* 20 bit GOT offset. */
+#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */
+#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS
+ block offset. */
+#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */
+/* Keep this the last entry. */
+#define R_390_NUM 62
+
+
+/* CRIS relocations. */
+#define R_CRIS_NONE 0
+#define R_CRIS_8 1
+#define R_CRIS_16 2
+#define R_CRIS_32 3
+#define R_CRIS_8_PCREL 4
+#define R_CRIS_16_PCREL 5
+#define R_CRIS_32_PCREL 6
+#define R_CRIS_GNU_VTINHERIT 7
+#define R_CRIS_GNU_VTENTRY 8
+#define R_CRIS_COPY 9
+#define R_CRIS_GLOB_DAT 10
+#define R_CRIS_JUMP_SLOT 11
+#define R_CRIS_RELATIVE 12
+#define R_CRIS_16_GOT 13
+#define R_CRIS_32_GOT 14
+#define R_CRIS_16_GOTPLT 15
+#define R_CRIS_32_GOTPLT 16
+#define R_CRIS_32_GOTREL 17
+#define R_CRIS_32_PLT_GOTREL 18
+#define R_CRIS_32_PLT_PCREL 19
+
+#define R_CRIS_NUM 20
+
+
+/* AMD x86-64 relocations. */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
+ offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
+#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset
+ to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset
+ to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset
+ to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
+#define R_X86_64_PC64 24 /* PC relative 64 bit */
+#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */
+#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative
+ offset to GOT */
+#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */
+#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset
+ to GOT entry */
+#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */
+#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */
+#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset
+ to PLT entry */
+#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */
+#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */
+#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */
+#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS
+ descriptor. */
+#define R_X86_64_TLSDESC 36 /* TLS descriptor. */
+#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */
+#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */
+
+#define R_X86_64_NUM 39
+
+
+/* AM33 relocations. */
+#define R_MN10300_NONE 0 /* No reloc. */
+#define R_MN10300_32 1 /* Direct 32 bit. */
+#define R_MN10300_16 2 /* Direct 16 bit. */
+#define R_MN10300_8 3 /* Direct 8 bit. */
+#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */
+#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */
+#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
+#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */
+#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */
+#define R_MN10300_24 9 /* Direct 24 bit. */
+#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */
+#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */
+#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */
+#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */
+#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */
+#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */
+#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */
+#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */
+#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */
+#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */
+#define R_MN10300_COPY 20 /* Copy symbol at runtime. */
+#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */
+#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */
+#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
+
+#define R_MN10300_NUM 24
+
+
+/* M32R relocs. */
+#define R_M32R_NONE 0 /* No reloc. */
+#define R_M32R_16 1 /* Direct 16 bit. */
+#define R_M32R_32 2 /* Direct 32 bit. */
+#define R_M32R_24 3 /* Direct 24 bit. */
+#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */
+#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */
+#define R_M32R_LO16 9 /* Low 16 bit. */
+#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */
+#define R_M32R_GNU_VTINHERIT 11
+#define R_M32R_GNU_VTENTRY 12
+/* M32R relocs use SHT_RELA. */
+#define R_M32R_16_RELA 33 /* Direct 16 bit. */
+#define R_M32R_32_RELA 34 /* Direct 32 bit. */
+#define R_M32R_24_RELA 35 /* Direct 24 bit. */
+#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */
+#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */
+#define R_M32R_LO16_RELA 41 /* Low 16 bit */
+#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */
+#define R_M32R_RELA_GNU_VTINHERIT 43
+#define R_M32R_RELA_GNU_VTENTRY 44
+#define R_M32R_REL32 45 /* PC relative 32 bit. */
+
+#define R_M32R_GOT24 48 /* 24 bit GOT entry */
+#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */
+#define R_M32R_COPY 50 /* Copy symbol at runtime */
+#define R_M32R_GLOB_DAT 51 /* Create GOT entry */
+#define R_M32R_JMP_SLOT 52 /* Create PLT entry */
+#define R_M32R_RELATIVE 53 /* Adjust by program base */
+#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */
+#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */
+#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned
+ low */
+#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed
+ low */
+#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */
+#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to
+ GOT with unsigned low */
+#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to
+ GOT with signed low */
+#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to
+ GOT */
+#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT
+ with unsigned low */
+#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT
+ with signed low */
+#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */
+#define R_M32R_NUM 256 /* Keep this the last entry. */
+
+
+/* TILEPro relocations. */
+#define R_TILEPRO_NONE 0 /* No reloc */
+#define R_TILEPRO_32 1 /* Direct 32 bit */
+#define R_TILEPRO_16 2 /* Direct 16 bit */
+#define R_TILEPRO_8 3 /* Direct 8 bit */
+#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */
+#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */
+#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */
+#define R_TILEPRO_LO16 7 /* Low 16 bit */
+#define R_TILEPRO_HI16 8 /* High 16 bit */
+#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */
+#define R_TILEPRO_COPY 10 /* Copy relocation */
+#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */
+#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */
+#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */
+#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */
+#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */
+#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */
+#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */
+#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */
+#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */
+#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */
+#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */
+#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */
+#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */
+#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */
+#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */
+#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */
+#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */
+#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */
+#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */
+#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */
+#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */
+#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */
+#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */
+#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */
+#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */
+#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */
+#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */
+#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */
+#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */
+#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */
+#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */
+#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */
+#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */
+#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */
+#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */
+#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */
+#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */
+#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */
+/* Relocs 56-59 are currently not defined. */
+#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */
+#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */
+#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */
+#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */
+#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */
+#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */
+#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */
+#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */
+
+#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */
+#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */
+
+#define R_TILEPRO_NUM 130
+
+
+/* TILE-Gx relocations. */
+#define R_TILEGX_NONE 0 /* No reloc */
+#define R_TILEGX_64 1 /* Direct 64 bit */
+#define R_TILEGX_32 2 /* Direct 32 bit */
+#define R_TILEGX_16 3 /* Direct 16 bit */
+#define R_TILEGX_8 4 /* Direct 8 bit */
+#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */
+#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */
+#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */
+#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */
+#define R_TILEGX_HW0 9 /* hword 0 16-bit */
+#define R_TILEGX_HW1 10 /* hword 1 16-bit */
+#define R_TILEGX_HW2 11 /* hword 2 16-bit */
+#define R_TILEGX_HW3 12 /* hword 3 16-bit */
+#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */
+#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */
+#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */
+#define R_TILEGX_COPY 16 /* Copy relocation */
+#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */
+#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */
+#define R_TILEGX_RELATIVE 19 /* Adjust by program base */
+#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */
+#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */
+#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */
+#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */
+#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */
+#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */
+#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */
+#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */
+#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */
+#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */
+#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */
+#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */
+#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */
+#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */
+#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */
+#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */
+#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */
+#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */
+#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */
+#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */
+#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */
+#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */
+#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */
+#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */
+#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */
+#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */
+#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */
+/* Relocs 66-71 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */
+#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */
+#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */
+#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */
+/* Relocs 76-77 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */
+#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */
+/* Relocs 90-91 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */
+/* Relocs 94-99 are currently not defined. */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */
+/* Relocs 104-105 are currently not defined. */
+#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */
+#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */
+#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */
+#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */
+#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */
+#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */
+#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */
+#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */
+#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */
+#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */
+
+#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */
+#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */
+
+#define R_TILEGX_NUM 130
+
+#endif /* elf.h */
diff --git a/tools/include/endian.h b/tools/include/endian.h
new file mode 100644
index 0000000..bba70ab
--- /dev/null
+++ b/tools/include/endian.h
@@ -0,0 +1,40 @@
+#ifndef __endian_compat_h
+#define __endian_compat_h
+
+#if defined(__linux__) || defined(__CYGWIN__)
+#include <byteswap.h>
+#include_next <endian.h>
+#elif defined(__APPLE__)
+#include <machine/endian.h>
+#include <machine/byte_order.h>
+#define bswap_16(x) NXSwapShort(x)
+#define bswap_32(x) NXSwapInt(x)
+#define bswap_64(x) NXSwapLongLong(x)
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+#elif defined(__OpenBSD__)
+#include <sys/types.h>
+#define bswap_16(x) __swap16(x)
+#define bswap_32(x) __swap32(x)
+#define bswap_64(x) __swap64(x)
+#else
+#include <machine/endian.h>
+#define bswap_16(x) swap16(x)
+#define bswap_32(x) swap32(x)
+#define bswap_64(x) swap64(x)
+#endif
+
+#ifndef __BYTE_ORDER
+#define __BYTE_ORDER BYTE_ORDER
+#endif
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN BIG_ENDIAN
+#endif
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#endif
+
+#endif
diff --git a/tools/include/getline.h b/tools/include/getline.h
new file mode 100644
index 0000000..7b320f7
--- /dev/null
+++ b/tools/include/getline.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2006 SPARTA, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by SPARTA ISSO under SPAWAR contract
+ * N66001-04-C-6019 ("SEFOS").
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __FreeBSD__
+#include <osreldate.h>
+#endif
+
+#if !defined(__linux__) && !defined(__OpenBSD__) && !(defined(__APPLE__) && __DARWIN_C_LEVEL >= 200809L) && !(defined(__FreeBSD__) && __FreeBSD_version >= 800000)
+/*
+ * Emulate glibc getline() via BSD fgetln().
+ * Note that outsize is not changed unless memory is allocated.
+ */
+static inline ssize_t
+getline(char **outbuf, size_t *outsize, FILE *fp)
+{
+ size_t len;
+
+#ifndef __CYGWIN__
+ char *buf;
+ buf = fgetln(fp, &len);
+#else
+ char buf[512];
+ fgets(buf, sizeof(buf), fp);
+ len = strlen(buf);
+#endif
+ if (buf == NULL)
+ return (-1);
+
+ /* Assumes realloc() accepts NULL for ptr (C99) */
+ if (*outbuf == NULL || *outsize < len + 1) {
+ void *tmp = realloc(*outbuf, len + 1);
+ if (tmp == NULL)
+ return (-1);
+ *outbuf = tmp;
+ *outsize = len + 1;
+ }
+ memcpy(*outbuf, buf, len);
+ (*outbuf)[len] = '\0';
+ return (len);
+}
+#endif
diff --git a/tools/include/sys/sysmacros.h b/tools/include/sys/sysmacros.h
new file mode 100644
index 0000000..997d928
--- /dev/null
+++ b/tools/include/sys/sysmacros.h
@@ -0,0 +1,56 @@
+/* Definitions of macros to access `dev_t' values.
+ Copyright (C) 1996, 1997, 1999, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef __SYS_SYSMACROS_H
+#define __SYS_SYSMACROS_H 1
+
+static inline unsigned int
+__gnu_dev_major(unsigned long long int __dev)
+{
+ return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);
+}
+
+static inline unsigned int
+__gnu_dev_minor(unsigned long long int __dev)
+{
+ return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);
+}
+
+static inline unsigned long long int
+__gnu_dev_makedev(unsigned int __major, unsigned int __minor)
+{
+ return ((__minor & 0xff) | ((__major & 0xfff) << 8)
+ | (((unsigned long long int) (__minor & ~0xff)) << 12)
+ | (((unsigned long long int) (__major & ~0xfff)) << 32));
+}
+
+/* Access the functions with their traditional names. */
+#ifndef major
+# define major(dev) __gnu_dev_major (dev)
+#endif
+
+#ifndef minor
+# define minor(dev) __gnu_dev_minor (dev)
+#endif
+
+#ifndef makedev
+# define makedev(maj, min) __gnu_dev_makedev (maj, min)
+#endif
+
+#endif /* sys/sysmacros.h */
diff --git a/tools/libelf/Makefile b/tools/libelf/Makefile
new file mode 100644
index 0000000..8036b6f
--- /dev/null
+++ b/tools/libelf/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libelf
+PKG_VERSION:=0.8.13
+PKG_MD5SUM:=4136d7b4c04df68b686570afa26988ac
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.mr511.de/software/
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += \
+ --disable-shared \
+ --enable-elf64
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR)/$(3); \
+ $(HOST_CONFIGURE_CMD) \
+ $(HOST_CONFIGURE_ARGS); \
+ )
+endef
+
+
+define Host/Compile
+ +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR)/lib/ libelf.a
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/{lib,include/libelf}
+ $(CP) $(HOST_BUILD_DIR)/lib/{elf_repl.h,gelf.h,libelf.h,nlist.h,sys_elf.h} \
+ $(STAGING_DIR_HOST)/include/libelf/
+ $(CP) $(HOST_BUILD_DIR)/lib/libelf.a $(STAGING_DIR_HOST)/lib/
+endef
+
+define Host/Clean
+ rm -rf $(STAGING_DIR_HOST)/include/libelf
+ rm -f $(STAGING_DIR_HOST)/lib/libelf.a
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/libtool/Makefile b/tools/libtool/Makefile
new file mode 100644
index 0000000..9fab8d9
--- /dev/null
+++ b/tools/libtool/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2008-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libtool
+PKG_VERSION:=2.4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=b32b04148ecdd7344abc6fe8bd1bb021
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_VARS += \
+ lt_cv_sys_dlsearch_path=""
+
+define Host/Prepare
+ $(call Host/Prepare/Default)
+ (cd $(STAGING_DIR_HOST)/share/aclocal/ && rm -f libtool.m4 ltdl.m4 lt~obsolete.m4 ltoptions.m4 ltsugar.m4 ltversion.m4)
+ (cd $(HOST_BUILD_DIR); $(AM_TOOL_PATHS) ./bootstrap)
+endef
+
+define Host/Install
+ $(MAKE) -C $(HOST_BUILD_DIR) install
+ $(SED) 's,\(hardcode_into_libs\)=yes,\1=no,g' $(STAGING_DIR_HOST)/bin/libtool
+ $(CP) $(STAGING_DIR_HOST)/bin/libtool $(STAGING_DIR_HOST)/bin/libtool-ucxx
+ $(SED) 's,-lstdc++,-luClibc++,g' $(STAGING_DIR_HOST)/bin/libtool-ucxx
+endef
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/libtool/files/libtool-v1.5.patch b/tools/libtool/files/libtool-v1.5.patch
new file mode 100644
index 0000000..485dfc7
--- /dev/null
+++ b/tools/libtool/files/libtool-v1.5.patch
@@ -0,0 +1,118 @@
+--- a/ltmain.sh
++++ b/ltmain.sh
+@@ -35,7 +35,7 @@ progpath="$0"
+
+ # The name of this program:
+ progname=`echo "$progpath" | $SED $basename`
+-modename="$progname"
++modename="OpenWrt-$progname-patched-1.5"
+
+ # Global variables:
+ EXIT_SUCCESS=0
+@@ -297,8 +297,8 @@ func_infer_tag ()
+ # line option must be used.
+ if test -z "$tagname"; then
+ $echo "$modename: unable to infer tagged configuration"
+- $echo "$modename: specify a tag with \`--tag'" 1>&2
+- exit $EXIT_FAILURE
++ $echo "$modename: defaulting to \`CC'"
++ $echo "$modename: if this is not correct, specify a tag with \`--tag'"
+ # else
+ # $echo "$modename: using $tagname tagged configuration"
+ fi
+@@ -2462,8 +2462,14 @@ EOF
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+- dir="$libdir"
+- absdir="$libdir"
++ # Adding 'libdir' from the .la file to our library search paths
++ # breaks crosscompilation horribly. We cheat here and don't add
++ # it, instead adding the path where we found the .la. -CL
++ dir="$lt_sysroot$abs_ladir"
++ absdir="$abs_ladir"
++ libdir="$abs_ladir"
++ #dir="$libdir"
++ #absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+@@ -2602,7 +2608,7 @@ EOF
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+- need_relink=yes
++ need_relink=no
+ fi
+ # This is a shared library
+
+@@ -2804,7 +2810,6 @@ EOF
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+- add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+@@ -2820,8 +2825,6 @@ EOF
+ add="$libdir/$linklib"
+ fi
+ else
+- # We cannot seem to hardcode it, guess we'll fake it.
+- add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+@@ -5687,6 +5690,10 @@ fi\
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
++ # Replacing uninstalled with installed can easily break crosscompilation,
++ # since the installed path is generally the wrong architecture. -CL
++ newdependency_libs="$newdependency_libs $deplib"
++ continue
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+@@ -5999,8 +6006,12 @@ relink_command=\"$relink_command\""
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
++ # Strip any trailing slash from the destination.
++ s_libdir=`$echo "X$libdir" | $Xsed -e 's%/$%%'`
++ s_destdir=`$echo "X$destdir" | $Xsed -e 's%/$%%'`
++
+ # Determine the prefix the user has applied to our future dir.
+- inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
++ inst_prefix_dir=`$echo "$s_destdir" | $SED "s%$s_libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+@@ -6008,10 +6019,13 @@ relink_command=\"$relink_command\""
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+- if test "$inst_prefix_dir" = "$destdir"; then
+- $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+- exit $EXIT_FAILURE
+- fi
++ #
++ # This breaks install into our staging area. -PB
++ #
++ # if test "$inst_prefix_dir" = "$destdir"; then
++ # $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
++ # exit $EXIT_FAILURE
++ # fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+@@ -6020,6 +6034,9 @@ relink_command=\"$relink_command\""
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
+ fi
+
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"`
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"`
++
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
diff --git a/tools/libtool/files/libtool-v2.2.patch b/tools/libtool/files/libtool-v2.2.patch
new file mode 100644
index 0000000..03994ba
--- /dev/null
+++ b/tools/libtool/files/libtool-v2.2.patch
@@ -0,0 +1,123 @@
+--- a/ltmain.sh
++++ b/ltmain.sh
+@@ -243,7 +243,7 @@ opt_warning=:
+ # name if it has been set yet.
+ func_echo ()
+ {
+- $ECHO "$progname${mode+: }$mode: $*"
++ $ECHO "OpenWrt-$progname-patched-2.2${mode+: }$mode: $*"
+ }
+
+ # func_verbose arg...
+@@ -262,14 +262,14 @@ func_verbose ()
+ # Echo program name prefixed message to standard error.
+ func_error ()
+ {
+- $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
++ $ECHO "OpenWrt-$progname-patched-2.2${mode+: }$mode: "${1+"$@"} 1>&2
+ }
+
+ # func_warning arg...
+ # Echo program name prefixed warning message to standard error.
+ func_warning ()
+ {
+- $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
++ $opt_warning && $ECHO "OpenWrt-$progname-patched-2.2${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+@@ -1048,8 +1048,8 @@ func_infer_tag ()
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+- func_echo "unable to infer tagged configuration"
+- func_fatal_error "specify a tag with \`--tag'"
++ func_echo "defaulting to \`CC'"
++ func_echo "if this is not correct, specify a tag with \`--tag'"
+ # else
+ # func_verbose "using $tagname tagged configuration"
+ fi
+@@ -2009,8 +2009,15 @@ func_mode_install ()
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
++ # Strip any trailing slash from the destination.
++ func_stripname '' '/' "$libdir"
++ s_libdir=$func_stripname_result
++
++ func_stripname '' '/' "$destdir"
++ s_destdir=$func_stripname_result
++
+ # Determine the prefix the user has applied to our future dir.
+- inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
++ inst_prefix_dir=`$ECHO "X$s_destdir" | $Xsed -e "s%$s_libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+@@ -2018,8 +2025,11 @@ func_mode_install ()
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+- test "$inst_prefix_dir" = "$destdir" && \
+- func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
++ #
++ # This breaks install into our staging area. -PB
++ #
++ # test "$inst_prefix_dir" = "$destdir" && \
++ # func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+@@ -2028,6 +2038,9 @@ func_mode_install ()
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
+ fi
+
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"`
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"`
++
+ func_warning "relinking \`$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+@@ -5412,8 +5425,12 @@ func_mode_link ()
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+- dir="$libdir"
+- absdir="$libdir"
++ # Adding 'libdir' from the .la file to our library search paths
++ # breaks crosscompilation horribly. We cheat here and don't add
++ # it, instead adding the path where we found the .la. -CL
++ dir="$abs_ladir"
++ absdir="$abs_ladir"
++ libdir="$abs_ladir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+@@ -5564,7 +5581,7 @@ func_mode_link ()
+ *)
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+- need_relink=yes
++ need_relink=no
+ fi
+ ;;
+ esac
+@@ -5768,7 +5785,6 @@ func_mode_link ()
+ test "$hardcode_direct_absolute" = no; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+- add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+@@ -8052,6 +8068,10 @@ EOF
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
++ # Replacing uninstalled with installed can easily break crosscompilation,
++ # since the installed path is generally the wrong architecture. -CL
++ newdependency_libs="$newdependency_libs $deplib"
++ continue
+ case $deplib in
+ *.la)
+ func_basename "$deplib"
diff --git a/tools/libtool/files/libtool-v2.4.patch b/tools/libtool/files/libtool-v2.4.patch
new file mode 100644
index 0000000..afc754a
--- /dev/null
+++ b/tools/libtool/files/libtool-v2.4.patch
@@ -0,0 +1,160 @@
+--- a/ltmain.sh
++++ b/ltmain.sh
+@@ -443,7 +443,7 @@ opt_warning=:
+ # name if it has been set yet.
+ func_echo ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
++ $ECHO "OpenWrt-$progname-patched-2.4: ${opt_mode+$opt_mode: }$*"
+ }
+
+ # func_verbose arg...
+@@ -469,14 +469,14 @@ func_echo_all ()
+ # Echo program name prefixed message to standard error.
+ func_error ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
++ $ECHO "OpenWrt-$progname-patched-2.4: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+ }
+
+ # func_warning arg...
+ # Echo program name prefixed warning message to standard error.
+ func_warning ()
+ {
+- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
++ $opt_warning && $ECHO "OpenWrt-$progname-patched-2.4: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+@@ -1416,8 +1416,8 @@ func_infer_tag ()
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+- func_echo "unable to infer tagged configuration"
+- func_fatal_error "specify a tag with \`--tag'"
++ func_echo "defaulting to \`CC'"
++ func_echo "if this is not correct, specify a tag with \`--tag'"
+ # else
+ # func_verbose "using $tagname tagged configuration"
+ fi
+@@ -2953,8 +2953,15 @@ func_mode_install ()
+ func_append dir "$objdir"
+
+ if test -n "$relink_command"; then
++ # Strip any trailing slash from the destination.
++ func_stripname '' '/' "$libdir"
++ s_libdir=$func_stripname_result
++
++ func_stripname '' '/' "$destdir"
++ s_destdir=$func_stripname_result
++
+ # Determine the prefix the user has applied to our future dir.
+- inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
++ inst_prefix_dir=`$ECHO "$s_destdir" | $SED -e "s%$s_libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+@@ -2962,8 +2969,11 @@ func_mode_install ()
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+- test "$inst_prefix_dir" = "$destdir" && \
+- func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
++ #
++ # This breaks install into our staging area. -PB
++ #
++ # test "$inst_prefix_dir" = "$destdir" && \
++ # func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+@@ -2972,6 +2982,9 @@ func_mode_install ()
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"`
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"`
++
+ func_warning "relinking \`$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+@@ -6504,8 +6517,12 @@ func_mode_link ()
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+- dir="$lt_sysroot$libdir"
+- absdir="$lt_sysroot$libdir"
++ # Adding 'libdir' from the .la file to our library search paths
++ # breaks crosscompilation horribly. We cheat here and don't add
++ # it, instead adding the path where we found the .la. -CL
++ dir="$lt_sysroot$abs_ladir"
++ absdir="$abs_ladir"
++ libdir="$abs_ladir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+@@ -6683,7 +6700,7 @@ func_mode_link ()
+ *)
+ if test "$installed" = no; then
+ func_append notinst_deplibs " $lib"
+- need_relink=yes
++ need_relink=no
+ fi
+ ;;
+ esac
+@@ -6887,7 +6904,6 @@ func_mode_link ()
+ test "$hardcode_direct_absolute" = no; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+- add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+@@ -6903,8 +6919,6 @@ func_mode_link ()
+ add="$libdir/$linklib"
+ fi
+ else
+- # We cannot seem to hardcode it, guess we'll fake it.
+- add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+@@ -7059,7 +7073,17 @@ func_mode_link ()
+ fi
+ ;;
+ *)
+- path="-L$absdir/$objdir"
++ # OE sets installed=no in staging. We need to look in $objdir and $absdir,
++ # preferring $objdir. RP 31/04/2008
++ if test -f "$absdir/$objdir/$depdepl" ; then
++ depdepl="$absdir/$objdir/$depdepl"
++ path="-L$absdir/$objdir"
++ elif test -f "$absdir/$depdepl" ; then
++ depdepl="$absdir/$depdepl"
++ path="-L$absdir"
++ else
++ path="-L$absdir/$objdir"
++ fi
+ ;;
+ esac
+ else
+@@ -8050,7 +8074,7 @@ EOF
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+- *) func_apped perm_rpath " $libdir" ;;
++ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+@@ -9257,6 +9281,10 @@ EOF
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
++ # Replacing uninstalled with installed can easily break crosscompilation,
++ # since the installed path is generally the wrong architecture. -CL
++ newdependency_libs="$newdependency_libs $deplib"
++ continue
+ case $deplib in
+ *.la)
+ func_basename "$deplib"
diff --git a/tools/libtool/patches/000-relocatable.patch b/tools/libtool/patches/000-relocatable.patch
new file mode 100644
index 0000000..55265fe
--- /dev/null
+++ b/tools/libtool/patches/000-relocatable.patch
@@ -0,0 +1,141 @@
+--- a/libltdl/config/general.m4sh
++++ b/libltdl/config/general.m4sh
+@@ -45,15 +45,22 @@ progpath="$0"
+ M4SH_VERBATIM([[
+ : ${CP="cp -f"}
+ test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
+-: ${EGREP="@EGREP@"}
+-: ${FGREP="@FGREP@"}
+-: ${GREP="@GREP@"}
+ : ${LN_S="@LN_S@"}
+ : ${MAKE="make"}
+ : ${MKDIR="mkdir"}
+ : ${MV="mv -f"}
+ : ${RM="rm -f"}
+-: ${SED="@SED@"}
++if test -n "$STAGING_DIR"; then
++ : ${EGREP="$STAGING_DIR/../host/bin/grep -E"}
++ : ${FGREP="$STAGING_DIR/../host/bin/grep -F"}
++ : ${GREP="$STAGING_DIR/../host/bin/grep"}
++ : ${SED="$STAGING_DIR/../host/bin/sed"}
++else
++ : ${EGREP="@EGREP@"}
++ : ${FGREP="@FGREP@"}
++ : ${GREP="@GREP@"}
++ : ${SED="@SED@"}
++fi
+ : ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+ : ${Xsed="$SED -e 1s/^X//"}
+
+--- a/libtoolize.in
++++ b/libtoolize.in
+@@ -326,15 +326,22 @@ as_unset=as_fn_unset
+
+ : ${CP="cp -f"}
+ test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
+-: ${EGREP="@EGREP@"}
+-: ${FGREP="@FGREP@"}
+-: ${GREP="@GREP@"}
+ : ${LN_S="@LN_S@"}
+ : ${MAKE="make"}
+ : ${MKDIR="mkdir"}
+ : ${MV="mv -f"}
+ : ${RM="rm -f"}
+-: ${SED="@SED@"}
++if test -n "$STAGING_DIR"; then
++ : ${EGREP="$STAGING_DIR/../host/bin/grep -E"}
++ : ${FGREP="$STAGING_DIR/../host/bin/grep -F"}
++ : ${GREP="$STAGING_DIR/../host/bin/grep"}
++ : ${SED="$STAGING_DIR/../host/bin/sed"}
++else
++ : ${EGREP="@EGREP@"}
++ : ${FGREP="@FGREP@"}
++ : ${GREP="@GREP@"}
++ : ${SED="@SED@"}
++fi
+ : ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+ : ${Xsed="$SED -e 1s/^X//"}
+
+@@ -2476,10 +2483,17 @@ func_check_macros ()
+
+ # Locations for important files:
+ prefix=@prefix@
+- datadir=@datadir@
+- pkgdatadir=@pkgdatadir@
+- pkgltdldir=@pkgdatadir@
+- aclocaldir=@aclocaldir@
++ if test -n "$STAGING_DIR"; then
++ datadir="$STAGING_DIR/../host/share"
++ pkgdatadir="$STAGING_DIR/../host/share/libtool"
++ pkgltdldir="$STAGING_DIR/../host/share/libtool"
++ aclocaldir="$STAGING_DIR/../host/share/aclocal"
++ else
++ datadir=@datadir@
++ pkgdatadir=@pkgdatadir@
++ pkgltdldir=@pkgdatadir@
++ aclocaldir=@aclocaldir@
++ fi
+ auxdir=
+ macrodir=
+ configure_ac=configure.in
+--- a/libtoolize.m4sh
++++ b/libtoolize.m4sh
+@@ -1450,10 +1450,17 @@ func_check_macros ()
+
+ # Locations for important files:
+ prefix=@prefix@
+- datadir=@datadir@
+- pkgdatadir=@pkgdatadir@
+- pkgltdldir=@pkgdatadir@
+- aclocaldir=@aclocaldir@
++ if test -n "$STAGING_DIR"; then
++ datadir="$STAGING_DIR/../host/share"
++ pkgdatadir="$STAGING_DIR/../host/share/libtool"
++ pkgltdldir="$STAGING_DIR/../host/share/libtool"
++ aclocaldir="$STAGING_DIR/../host/share/aclocal"
++ else
++ datadir=@datadir@
++ pkgdatadir=@pkgdatadir@
++ pkgltdldir=@pkgdatadir@
++ aclocaldir=@aclocaldir@
++ fi
+ auxdir=
+ macrodir=
+ configure_ac=configure.in
+--- a/libltdl/m4/libtool.m4
++++ b/libltdl/m4/libtool.m4
+@@ -875,9 +875,8 @@ dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+ # ----------------
+ m4_defun([_LT_TAG_COMPILER],
+ [AC_REQUIRE([AC_PROG_CC])dnl
+-
+ _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+-_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
++_LT_DECL([LTCFLAGS], [CFLAGS], ["-O2 -I\${STAGING_DIR:-$STAGING_DIR}/../host/include"], [LTCC compiler flags])dnl
+ _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+ _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+@@ -7509,9 +7508,9 @@ m4_defun([_LT_DECL_EGREP],
+ [AC_REQUIRE([AC_PROG_EGREP])dnl
+ AC_REQUIRE([AC_PROG_FGREP])dnl
+ test -z "$GREP" && GREP=grep
+-_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+-_LT_DECL([], [EGREP], [1], [An ERE matcher])
+-_LT_DECL([], [FGREP], [1], [A literal string matcher])
++_LT_DECL([], [GREP], ["\${STAGING_DIR:-$STAGING_DIR}/../host/bin/grep"], [A grep program that handles long lines])
++_LT_DECL([], [EGREP], ["\${STAGING_DIR:-$STAGING_DIR}/../host/bin/grep -E"], [An ERE matcher])
++_LT_DECL([], [FGREP], ["\${STAGING_DIR:-$STAGING_DIR}/../host/bin/grep -F"], [A literal string matcher])
+ dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+ AC_SUBST([GREP])
+ ])
+@@ -7544,9 +7543,8 @@ AC_SUBST([DLLTOOL])
+ # as few characters as possible. Prefer GNU sed if found.
+ m4_defun([_LT_DECL_SED],
+ [AC_PROG_SED
+-test -z "$SED" && SED=sed
+ Xsed="$SED -e 1s/^X//"
+-_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
++_LT_DECL([], [SED], ["\${STAGING_DIR:-$STAGING_DIR}/../host/bin/sed"], [A sed program that does not truncate output])
+ _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+ ])# _LT_DECL_SED
diff --git a/tools/libtool/patches/001-fix-func_append.patch b/tools/libtool/patches/001-fix-func_append.patch
new file mode 100644
index 0000000..4c3c07b
--- /dev/null
+++ b/tools/libtool/patches/001-fix-func_append.patch
@@ -0,0 +1,22 @@
+--- a/libltdl/config/ltmain.m4sh
++++ b/libltdl/config/ltmain.m4sh
+@@ -7261,7 +7261,7 @@ EOF
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+- *) func_apped perm_rpath " $libdir" ;;
++ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+--- a/libltdl/config/ltmain.sh
++++ b/libltdl/config/ltmain.sh
+@@ -8050,7 +8050,7 @@ EOF
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+- *) func_apped perm_rpath " $libdir" ;;
++ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
diff --git a/tools/libtool/patches/100-libdir-fixes.patch b/tools/libtool/patches/100-libdir-fixes.patch
new file mode 100644
index 0000000..d4e6f78
--- /dev/null
+++ b/tools/libtool/patches/100-libdir-fixes.patch
@@ -0,0 +1,94 @@
+--- a/libltdl/config/ltmain.m4sh
++++ b/libltdl/config/ltmain.m4sh
+@@ -5715,8 +5715,14 @@ func_mode_link ()
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+- dir="$lt_sysroot$libdir"
+- absdir="$lt_sysroot$libdir"
++ # Adding 'libdir' from the .la file to our library search paths
++ # breaks crosscompilation horribly. We cheat here and don't add
++ # it, instead adding the path where we found the .la. -CL
++ dir="$lt_sysroot$abs_ladir"
++ absdir="$abs_ladir"
++ libdir="$abs_ladir"
++ #dir="$libdir"
++ #absdir="$lt_sysroot$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+@@ -6114,8 +6120,6 @@ func_mode_link ()
+ add="$libdir/$linklib"
+ fi
+ else
+- # We cannot seem to hardcode it, guess we'll fake it.
+- add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+@@ -6270,7 +6274,17 @@ func_mode_link ()
+ fi
+ ;;
+ *)
+- path="-L$absdir/$objdir"
++ # OE sets installed=no in staging. We need to look in $objdir and $absdir,
++ # preferring $objdir. RP 31/04/2008
++ if test -f "$absdir/$objdir/$depdepl" ; then
++ depdepl="$absdir/$objdir/$depdepl"
++ path="-L$absdir/$objdir"
++ elif test -f "$absdir/$depdepl" ; then
++ depdepl="$absdir/$depdepl"
++ path="-L$absdir"
++ else
++ path="-L$absdir/$objdir"
++ fi
+ ;;
+ esac
+ else
+--- a/libltdl/config/ltmain.sh
++++ b/libltdl/config/ltmain.sh
+@@ -6504,8 +6504,14 @@ func_mode_link ()
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+- dir="$lt_sysroot$libdir"
+- absdir="$lt_sysroot$libdir"
++ # Adding 'libdir' from the .la file to our library search paths
++ # breaks crosscompilation horribly. We cheat here and don't add
++ # it, instead adding the path where we found the .la. -CL
++ dir="$lt_sysroot$abs_ladir"
++ absdir="$abs_ladir"
++ libdir="$abs_ladir"
++ #dir="$libdir"
++ #absdir="$lt_sysroot$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+@@ -6903,8 +6909,6 @@ func_mode_link ()
+ add="$libdir/$linklib"
+ fi
+ else
+- # We cannot seem to hardcode it, guess we'll fake it.
+- add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+@@ -7059,7 +7063,17 @@ func_mode_link ()
+ fi
+ ;;
+ *)
+- path="-L$absdir/$objdir"
++ # OE sets installed=no in staging. We need to look in $objdir and $absdir,
++ # preferring $objdir. RP 31/04/2008
++ if test -f "$absdir/$objdir/$depdepl" ; then
++ depdepl="$absdir/$objdir/$depdepl"
++ path="-L$absdir/$objdir"
++ elif test -f "$absdir/$depdepl" ; then
++ depdepl="$absdir/$depdepl"
++ path="-L$absdir"
++ else
++ path="-L$absdir/$objdir"
++ fi
+ ;;
+ esac
+ else
diff --git a/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch b/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch
new file mode 100644
index 0000000..c780589
--- /dev/null
+++ b/tools/libtool/patches/110-dont-use-target-dir-for-relinking.patch
@@ -0,0 +1,20 @@
+--- a/libltdl/config/ltmain.m4sh
++++ b/libltdl/config/ltmain.m4sh
+@@ -6104,7 +6104,6 @@ func_mode_link ()
+ test "$hardcode_direct_absolute" = no; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+- add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+--- a/libltdl/config/ltmain.sh
++++ b/libltdl/config/ltmain.sh
+@@ -6893,7 +6893,6 @@ func_mode_link ()
+ test "$hardcode_direct_absolute" = no; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+- add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
diff --git a/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch b/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch
new file mode 100644
index 0000000..1c3df4c
--- /dev/null
+++ b/tools/libtool/patches/120-strip-unsafe-dirs-for-relinking.patch
@@ -0,0 +1,24 @@
+--- a/libltdl/config/ltmain.m4sh
++++ b/libltdl/config/ltmain.m4sh
+@@ -2183,6 +2183,9 @@ func_mode_install ()
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"`
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"`
++
+ func_warning "relinking \`$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+--- a/libltdl/config/ltmain.sh
++++ b/libltdl/config/ltmain.sh
+@@ -2972,6 +2972,9 @@ func_mode_install ()
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/lib[^[:space:]]*%%"`
++ relink_command=`$ECHO "$relink_command" | $SED "s%-L[[:space:]]*/usr/lib[^[:space:]]*%%"`
++
+ func_warning "relinking \`$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
diff --git a/tools/libtool/patches/150-trailingslash.patch b/tools/libtool/patches/150-trailingslash.patch
new file mode 100644
index 0000000..a01f9be
--- /dev/null
+++ b/tools/libtool/patches/150-trailingslash.patch
@@ -0,0 +1,49 @@
+A command like /bin/sh ../../i586-poky-linux-libtool --mode=install /usr/bin/install -c gck-roots-store-standalone.la '/media/data1/builds/poky1/tmp/work/core2-poky-linux/gnome-keyring-2.26.1-r1/image/usr/lib/gnome-keyring/standalone/' fails (e.g. gnome-keyring or pulseaudio)
+
+This is because libdir has a trailing slash which breaks the comparision.
+
+RP 2/1/10
+
+Merged a patch received from Gary Thomas <gary@mlbassoc.com>
+
+Date: 2010/07/12
+Nitin A Kamble <nitin.a.kamble@intel.com>
+
+--- a/libltdl/config/ltmain.m4sh
++++ b/libltdl/config/ltmain.m4sh
+@@ -2164,8 +2164,15 @@ func_mode_install ()
+ func_append dir "$objdir"
+
+ if test -n "$relink_command"; then
++ # Strip any trailing slash from the destination.
++ func_stripname '' '/' "$libdir"
++ destlibdir=$func_stripname_result
++
++ func_stripname '' '/' "$destdir"
++ s_destdir=$func_stripname_result
++
+ # Determine the prefix the user has applied to our future dir.
+- inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
++ inst_prefix_dir=`$ECHO "X$s_destdir" | $Xsed -e "s%$destlibdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+--- a/libltdl/config/ltmain.sh
++++ b/libltdl/config/ltmain.sh
+@@ -2953,8 +2953,15 @@ func_mode_install ()
+ func_append dir "$objdir"
+
+ if test -n "$relink_command"; then
++ # Strip any trailing slash from the destination.
++ func_stripname '' '/' "$libdir"
++ destlibdir=$func_stripname_result
++
++ func_stripname '' '/' "$destdir"
++ s_destdir=$func_stripname_result
++
+ # Determine the prefix the user has applied to our future dir.
+- inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
++ inst_prefix_dir=`$ECHO "X$s_destdir" | $Xsed -e "s%$destlibdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
diff --git a/tools/libtool/patches/160-passthrough-ssp.patch b/tools/libtool/patches/160-passthrough-ssp.patch
new file mode 100644
index 0000000..9fad9aa
--- /dev/null
+++ b/tools/libtool/patches/160-passthrough-ssp.patch
@@ -0,0 +1,12 @@
+diff -ur libtool-2.4.orig/libltdl/config/ltmain.m4sh libtool-2.4/libltdl/config/ltmain.m4sh
+--- libtool-2.4.orig/libltdl/config/ltmain.m4sh 2015-06-18 10:46:15.499996979 +0200
++++ libtool-2.4/libltdl/config/ltmain.m4sh 2015-06-18 10:48:24.686882213 +0200
+@@ -5061,7 +5061,7 @@
+ # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+- -O*|-flto*|-fwhopr*|-fuse-linker-plugin)
++ -O*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*)
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ func_append compile_command " $arg"
diff --git a/tools/libtool/patches/200-openwrt-branding.patch b/tools/libtool/patches/200-openwrt-branding.patch
new file mode 100644
index 0000000..dd3e3d6
--- /dev/null
+++ b/tools/libtool/patches/200-openwrt-branding.patch
@@ -0,0 +1,112 @@
+--- a/libltdl/config/general.m4sh
++++ b/libltdl/config/general.m4sh
+@@ -359,7 +359,7 @@ opt_warning=:
+ # name if it has been set yet.
+ func_echo ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*"
+ }
+
+ # func_verbose arg...
+@@ -385,14 +385,14 @@ func_echo_all ()
+ # Echo program name prefixed message to standard error.
+ func_error ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+ }
+
+ # func_warning arg...
+ # Echo program name prefixed warning message to standard error.
+ func_warning ()
+ {
+- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+--- a/libltdl/config/ltmain.sh
++++ b/libltdl/config/ltmain.sh
+@@ -443,7 +443,7 @@ opt_warning=:
+ # name if it has been set yet.
+ func_echo ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*"
+ }
+
+ # func_verbose arg...
+@@ -469,14 +469,14 @@ func_echo_all ()
+ # Echo program name prefixed message to standard error.
+ func_error ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+ }
+
+ # func_warning arg...
+ # Echo program name prefixed warning message to standard error.
+ func_warning ()
+ {
+- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+--- a/libtoolize.in
++++ b/libtoolize.in
+@@ -640,7 +640,7 @@ opt_warning=:
+ # name if it has been set yet.
+ func_echo ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*"
+ }
+
+ # func_verbose arg...
+@@ -666,14 +666,14 @@ func_echo_all ()
+ # Echo program name prefixed message to standard error.
+ func_error ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+ }
+
+ # func_warning arg...
+ # Echo program name prefixed warning message to standard error.
+ func_warning ()
+ {
+- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+--- a/tests/defs.in
++++ b/tests/defs.in
+@@ -588,7 +588,7 @@ opt_warning=:
+ # name if it has been set yet.
+ func_echo ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }$*"
+ }
+
+ # func_verbose arg...
+@@ -614,14 +614,14 @@ func_echo_all ()
+ # Echo program name prefixed message to standard error.
+ func_error ()
+ {
+- $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
++ $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+ }
+
+ # func_warning arg...
+ # Echo program name prefixed warning message to standard error.
+ func_warning ()
+ {
+- $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
++ $opt_warning && $ECHO "OpenWrt-$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
diff --git a/tools/lzma-old/Makefile b/tools/lzma-old/Makefile
new file mode 100644
index 0000000..08511b0
--- /dev/null
+++ b/tools/lzma-old/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lzma-old
+PKG_VERSION:=4.32
+
+PKG_SOURCE:=lzma-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources/
+PKG_MD5SUM:=5587d6ac230ad1903d504fc3253f0e42
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/lzma-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+LIB_DIR=$(HOST_BUILD_DIR)/C/7zip/Compress/LZMA_Lib
+ALONE_DIR=$(HOST_BUILD_DIR)/C/7zip/Compress/LZMA_Alone
+
+define Host/Compile
+ $(MAKE) -C $(LIB_DIR)
+ $(MAKE) -f makefile.gcc -C $(ALONE_DIR)
+endef
+
+define Host/Install
+ $(INSTALL_DATA) $(LIB_DIR)/liblzma.a $(STAGING_DIR_HOST)/lib/liblzma-old.a
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/lib/liblzma-old.a
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/lzma-old/patches/100-lzma_zlib.patch b/tools/lzma-old/patches/100-lzma_zlib.patch
new file mode 100644
index 0000000..32d1263
--- /dev/null
+++ b/tools/lzma-old/patches/100-lzma_zlib.patch
@@ -0,0 +1,404 @@
+--- a/C/7zip/Compress/LZMA/LZMADecoder.cpp
++++ b/C/7zip/Compress/LZMA/LZMADecoder.cpp
+@@ -274,12 +274,17 @@ STDMETHODIMP CDecoder::SetDecoderPropert
+ Byte remainder = (Byte)(properties[0] / 9);
+ int lp = remainder % 5;
+ int pb = remainder / 5;
+- if (pb > NLength::kNumPosStatesBitsMax)
+- return E_INVALIDARG;
+- _posStateMask = (1 << pb) - 1;
+ UInt32 dictionarySize = 0;
+ for (int i = 0; i < 4; i++)
+ dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
++ return SetDecoderPropertiesRaw(lc, lp, pb, dictionarySize);
++}
++
++STDMETHODIMP CDecoder::SetDecoderPropertiesRaw(int lc, int lp, int pb, UInt32 dictionarySize)
++{
++ if (pb > NLength::kNumPosStatesBitsMax)
++ return E_INVALIDARG;
++ _posStateMask = (1 << pb) - 1;
+ if (!_outWindowStream.Create(dictionarySize))
+ return E_OUTOFMEMORY;
+ if (!_literalDecoder.Create(lp, lc))
+--- a/C/7zip/Compress/LZMA/LZMADecoder.h
++++ b/C/7zip/Compress/LZMA/LZMADecoder.h
+@@ -228,6 +228,7 @@ public:
+ ICompressProgressInfo *progress);
+
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
++ STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize);
+
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
+--- /dev/null
++++ b/C/7zip/Compress/LZMA_Lib/makefile
+@@ -0,0 +1,92 @@
++PROG = liblzma.a
++CXX = g++ -O3 -Wall
++AR = ar
++RM = rm -f
++CFLAGS = -c -I ../../../
++
++OBJS = \
++ ZLib.o \
++ LZMADecoder.o \
++ LZMAEncoder.o \
++ LZInWindow.o \
++ LZOutWindow.o \
++ RangeCoderBit.o \
++ InBuffer.o \
++ OutBuffer.o \
++ FileStreams.o \
++ Alloc.o \
++ C_FileIO.o \
++ CommandLineParser.o \
++ CRC.o \
++ StreamUtils.o \
++ String.o \
++ StringConvert.o \
++ StringToInt.o \
++ Vector.o \
++
++
++all: $(PROG)
++
++$(PROG): $(OBJS)
++ $(AR) r $(PROG) $(OBJS)
++
++ZLib.o: ZLib.cpp
++ $(CXX) $(CFLAGS) ZLib.cpp
++
++LZMADecoder.o: ../LZMA/LZMADecoder.cpp
++ $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp
++
++LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp
++ $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp
++
++LZInWindow.o: ../LZ/LZInWindow.cpp
++ $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp
++
++LZOutWindow.o: ../LZ/LZOutWindow.cpp
++ $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp
++
++RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp
++ $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp
++
++InBuffer.o: ../../Common/InBuffer.cpp
++ $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp
++
++OutBuffer.o: ../../Common/OutBuffer.cpp
++ $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp
++
++StreamUtils.o: ../../Common/StreamUtils.cpp
++ $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
++
++FileStreams.o: ../../Common/FileStreams.cpp
++ $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp
++
++Alloc.o: ../../../Common/Alloc.cpp
++ $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp
++
++C_FileIO.o: ../../../Common/C_FileIO.cpp
++ $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp
++
++CommandLineParser.o: ../../../Common/CommandLineParser.cpp
++ $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp
++
++CRC.o: ../../../Common/CRC.cpp
++ $(CXX) $(CFLAGS) ../../../Common/CRC.cpp
++
++MyWindows.o: ../../../Common/MyWindows.cpp
++ $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
++
++String.o: ../../../Common/String.cpp
++ $(CXX) $(CFLAGS) ../../../Common/String.cpp
++
++StringConvert.o: ../../../Common/StringConvert.cpp
++ $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
++
++StringToInt.o: ../../../Common/StringToInt.cpp
++ $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
++
++Vector.o: ../../../Common/Vector.cpp
++ $(CXX) $(CFLAGS) ../../../Common/Vector.cpp
++
++clean:
++ -$(RM) $(PROG) $(OBJS)
++
+--- /dev/null
++++ b/C/7zip/Compress/LZMA_Lib/ZLib.cpp
+@@ -0,0 +1,273 @@
++/*
++ * lzma zlib simplified wrapper
++ *
++ * Copyright (c) 2005-2006 Oleg I. Vdovikin <oleg@cs.msu.su>
++ *
++ * This library is free software; you can redistribute
++ * it and/or modify it under the terms of the GNU Lesser
++ * General Public License as published by the Free Software
++ * Foundation; either version 2.1 of the License, or
++ * (at your option) any later version.
++ *
++ * 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 Lesser General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU Lesser General
++ * Public License along with this library; if not, write to
++ * the Free Software Foundation, Inc., 59 Temple Place,
++ * Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/*
++ * default values for encoder/decoder used by wrapper
++ */
++
++#include <zlib.h>
++
++#define ZLIB_LC 3
++#define ZLIB_LP 0
++#define ZLIB_PB 2
++
++#ifdef WIN32
++#include <initguid.h>
++#else
++#define INITGUID
++#endif
++
++#include "../../../Common/MyWindows.h"
++#include "../LZMA/LZMADecoder.h"
++#include "../LZMA/LZMAEncoder.h"
++
++#define STG_E_SEEKERROR ((HRESULT)0x80030019L)
++#define STG_E_MEDIUMFULL ((HRESULT)0x80030070L)
++
++class CInMemoryStream:
++ public IInStream,
++ public IStreamGetSize,
++ public CMyUnknownImp
++{
++public:
++ CInMemoryStream(const Bytef *data, UInt64 size) :
++ m_data(data), m_size(size), m_offset(0) {}
++
++ virtual ~CInMemoryStream() {}
++
++ MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
++
++ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize)
++ {
++ if (size > m_size - m_offset)
++ size = m_size - m_offset;
++
++ if (size) {
++ memcpy(data, m_data + m_offset, size);
++ }
++
++ m_offset += size;
++
++ if (processedSize)
++ *processedSize = size;
++
++ return S_OK;
++ }
++
++ STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize)
++ {
++ return Read(data, size, processedSize);
++ }
++
++ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
++ {
++ UInt64 _offset;
++
++ if (seekOrigin == STREAM_SEEK_SET) _offset = offset;
++ else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset;
++ else if (seekOrigin == STREAM_SEEK_END) _offset = m_size;
++ else return STG_E_INVALIDFUNCTION;
++
++ if (_offset < 0 || _offset > m_size)
++ return STG_E_SEEKERROR;
++
++ m_offset = _offset;
++
++ if (newPosition)
++ *newPosition = m_offset;
++
++ return S_OK;
++ }
++
++ STDMETHOD(GetSize)(UInt64 *size)
++ {
++ *size = m_size;
++ return S_OK;
++ }
++protected:
++ const Bytef *m_data;
++ UInt64 m_size;
++ UInt64 m_offset;
++};
++
++class COutMemoryStream:
++ public IOutStream,
++ public CMyUnknownImp
++{
++public:
++ COutMemoryStream(Bytef *data, UInt64 maxsize) :
++ m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {}
++ virtual ~COutMemoryStream() {}
++
++ MY_UNKNOWN_IMP1(IOutStream)
++
++ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize)
++ {
++ if (size > m_maxsize - m_offset)
++ size = m_maxsize - m_offset;
++
++ if (size) {
++ memcpy(m_data + m_offset, data, size);
++ }
++
++ m_offset += size;
++
++ if (m_offset > m_size)
++ m_size = m_offset;
++
++ if (processedSize)
++ *processedSize = size;
++
++ return S_OK;
++ }
++
++ STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize)
++ {
++ return Write(data, size, processedSize);
++ }
++
++ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
++ {
++ UInt64 _offset;
++
++ if (seekOrigin == STREAM_SEEK_SET) _offset = offset;
++ else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset;
++ else if (seekOrigin == STREAM_SEEK_END) _offset = m_size;
++ else return STG_E_INVALIDFUNCTION;
++
++ if (_offset < 0 || _offset > m_maxsize)
++ return STG_E_SEEKERROR;
++
++ m_offset = _offset;
++
++ if (newPosition)
++ *newPosition = m_offset;
++
++ return S_OK;
++ }
++
++ STDMETHOD(SetSize)(Int64 newSize)
++ {
++ if ((UInt64)newSize > m_maxsize)
++ return STG_E_MEDIUMFULL;
++
++ return S_OK;
++ }
++protected:
++ Bytef *m_data;
++ UInt64 m_size;
++ UInt64 m_maxsize;
++ UInt64 m_offset;
++};
++
++ZEXTERN int ZEXPORT compress2 (Bytef *dest, uLongf *destLen,
++ const Bytef *source, uLong sourceLen,
++ int level)
++{
++ CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen);
++ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
++
++ COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen);
++ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
++
++ NCompress::NLZMA::CEncoder *encoderSpec =
++ new NCompress::NLZMA::CEncoder;
++ CMyComPtr<ICompressCoder> encoder = encoderSpec;
++
++ PROPID propIDs[] =
++ {
++ NCoderPropID::kDictionarySize,
++ NCoderPropID::kPosStateBits,
++ NCoderPropID::kLitContextBits,
++ NCoderPropID::kLitPosBits,
++ NCoderPropID::kAlgorithm,
++ NCoderPropID::kNumFastBytes,
++ NCoderPropID::kMatchFinder,
++ NCoderPropID::kEndMarker
++ };
++ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
++
++ PROPVARIANT properties[kNumProps];
++ for (int p = 0; p < 6; p++)
++ properties[p].vt = VT_UI4;
++ properties[0].ulVal = UInt32(1 << (level + 14));
++ properties[1].ulVal = UInt32(ZLIB_PB);
++ properties[2].ulVal = UInt32(ZLIB_LC); // for normal files
++ properties[3].ulVal = UInt32(ZLIB_LP); // for normal files
++ properties[4].ulVal = UInt32(2);
++ properties[5].ulVal = UInt32(128);
++
++ properties[6].vt = VT_BSTR;
++ properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT4";
++
++ properties[7].vt = VT_BOOL;
++ properties[7].boolVal = VARIANT_TRUE;
++
++ if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
++ return Z_MEM_ERROR; // should not happen
++
++ HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
++ if (result == E_OUTOFMEMORY)
++ {
++ return Z_MEM_ERROR;
++ }
++ else if (result != S_OK)
++ {
++ return Z_BUF_ERROR; // should not happen
++ }
++
++ UInt64 fileSize;
++ outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize);
++ *destLen = fileSize;
++
++ return Z_OK;
++}
++
++ZEXTERN int ZEXPORT uncompress (Bytef *dest, uLongf *destLen,
++ const Bytef *source, uLong sourceLen)
++{
++ CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen);
++ CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
++
++ COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen);
++ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
++
++ NCompress::NLZMA::CDecoder *decoderSpec =
++ new NCompress::NLZMA::CDecoder;
++ CMyComPtr<ICompressCoder> decoder = decoderSpec;
++
++ if (decoderSpec->SetDecoderPropertiesRaw(ZLIB_LC,
++ ZLIB_LP, ZLIB_PB, (1 << 23)) != S_OK) return Z_DATA_ERROR;
++
++ UInt64 fileSize = *destLen;
++
++ if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
++ {
++ return Z_DATA_ERROR;
++ }
++
++ outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize);
++ *destLen = fileSize;
++
++ return Z_OK;
++}
diff --git a/tools/lzma-old/patches/110-ranlib.patch b/tools/lzma-old/patches/110-ranlib.patch
new file mode 100644
index 0000000..813b413
--- /dev/null
+++ b/tools/lzma-old/patches/110-ranlib.patch
@@ -0,0 +1,10 @@
+--- a/C/7zip/Compress/LZMA_Lib/makefile
++++ b/C/7zip/Compress/LZMA_Lib/makefile
+@@ -29,6 +29,7 @@ all: $(PROG)
+
+ $(PROG): $(OBJS)
+ $(AR) r $(PROG) $(OBJS)
++ ranlib $(PROG)
+
+ ZLib.o: ZLib.cpp
+ $(CXX) $(CFLAGS) ZLib.cpp
diff --git a/tools/lzma/Makefile b/tools/lzma/Makefile
new file mode 100644
index 0000000..4922f80
--- /dev/null
+++ b/tools/lzma/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lzma
+PKG_VERSION:=4.65
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources/
+PKG_MD5SUM:=434e51a018b4c8ef377bf81520a53af0
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+UTIL_DIR=$(HOST_BUILD_DIR)/C/LzmaUtil
+ALONE_DIR=$(HOST_BUILD_DIR)/CPP/7zip/Compress/LZMA_Alone
+
+define Host/Compile
+ $(MAKE) -C $(UTIL_DIR) -f makefile.gcc
+ $(MAKE) -C $(ALONE_DIR) -f makefile.gcc
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/CPP/7zip/Compress/LZMA_Alone/lzma_alone $(STAGING_DIR_HOST)/bin/lzma
+endef
+
+define Host/Clean
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/lzma/patches/001-large_files.patch b/tools/lzma/patches/001-large_files.patch
new file mode 100644
index 0000000..b95fe9e
--- /dev/null
+++ b/tools/lzma/patches/001-large_files.patch
@@ -0,0 +1,13 @@
+Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
+===================================================================
+--- lzma-4.65.orig/CPP/7zip/Compress/LZMA_Alone/makefile.gcc 2009-05-15 23:33:51.000000000 +0200
++++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc 2009-06-01 22:00:54.000000000 +0200
+@@ -3,7 +3,7 @@
+ CXX_C = gcc -O2 -Wall
+ LIB = -lm
+ RM = rm -f
+-CFLAGS = -c
++CFLAGS = -c -D_FILE_OFFSET_BITS=64
+
+ ifdef SystemDrive
+ IS_MINGW = 1
diff --git a/tools/lzma/patches/002-lzmp.patch b/tools/lzma/patches/002-lzmp.patch
new file mode 100644
index 0000000..72d881c
--- /dev/null
+++ b/tools/lzma/patches/002-lzmp.patch
@@ -0,0 +1,1059 @@
+Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzmp.cpp
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzmp.cpp 2009-06-01 22:01:10.000000000 +0200
+@@ -0,0 +1,895 @@
++/*
++ * LZMA command line tool similar to gzip to encode and decode LZMA files.
++ *
++ * Copyright (C) 2005 Ville Koskinen
++ *
++ * 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 Street, Fifth Floor, Boston, MA 02110-1301,
++ * USA.
++ */
++
++#include "../../../Common/MyInitGuid.h"
++
++#include <iostream>
++using std::cout;
++using std::cerr;
++using std::endl;
++
++#include <cstdio>
++#include <cstdlib>
++#include <cstring>
++
++#include <string>
++using std::string;
++#include <vector>
++using std::vector;
++typedef vector<string> stringVector;
++
++#include <unistd.h>
++#include <getopt.h>
++#include <signal.h>
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <utime.h>
++#include <sys/time.h> // futimes()
++
++// For Solaris
++#ifndef HAVE_FUTIMES
++//#define futimes(fd, tv) futimesat(fd, NULL, tv)
++#endif
++
++#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
++#include <fcntl.h>
++#include <io.h>
++#define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)
++#else
++#define MY_SET_BINARY_MODE(file)
++#endif
++
++#include "../../../7zip/Common/FileStreams.h"
++
++#include "../../../Common/Types.h"
++
++#include "../../../7zip/Compress/LzmaDecoder.h"
++#include "../../../7zip/Compress/LzmaEncoder.h"
++
++#include "Exception.h"
++
++#include "lzma_version.h"
++
++namespace lzma {
++
++const char *PROGRAM_VERSION = PACKAGE_VERSION;
++const char *PROGRAM_COPYRIGHT = "Copyright (C) 2006 Ville Koskinen";
++
++/* LZMA_Alone switches:
++ -a{N}: set compression mode - [0, 2], default: 2 (max)
++ -d{N}: set dictionary - [0,28], default: 23 (8MB)
++ -fb{N}: set number of fast bytes - [5, 255], default: 128
++ -lc{N}: set number of literal context bits - [0, 8], default: 3
++ -lp{N}: set number of literal pos bits - [0, 4], default: 0
++ -pb{N}: set number of pos bits - [0, 4], default: 2
++ -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,
++ pat2h, pat3h, pat4h, hc3, hc4], default: bt4
++*/
++
++struct lzma_option {
++ short compression_mode; // -a
++ short dictionary; // -d
++ short fast_bytes; // -fb
++ wchar_t *match_finder; // -mf
++ short literal_context_bits; // -lc
++ short literal_pos_bits; // -lp
++ short pos_bits; // -pb
++};
++
++/* The following is a mapping from gzip/bzip2 style -1 .. -9 compression modes
++ * to the corresponding LZMA compression modes. Thanks, Larhzu, for coining
++ * these. */
++const lzma_option option_mapping[] = {
++ { 0, 0, 0, NULL, 0, 0, 0}, // -0 (needed for indexing)
++ { 0, 16, 64, L"hc4", 3, 0, 2}, // -1
++ { 0, 20, 64, L"hc4", 3, 0, 2}, // -2
++ { 1, 19, 64, L"bt4", 3, 0, 2}, // -3
++ { 2, 20, 64, L"bt4", 3, 0, 2}, // -4
++ { 2, 21, 128, L"bt4", 3, 0, 2}, // -5
++ { 2, 22, 128, L"bt4", 3, 0, 2}, // -6
++ { 2, 23, 128, L"bt4", 3, 0, 2}, // -7
++ { 2, 24, 255, L"bt4", 3, 0, 2}, // -8
++ { 2, 25, 255, L"bt4", 3, 0, 2}, // -9
++};
++
++struct extension_pair {
++ char *from;
++ char *to;
++};
++
++const extension_pair known_extensions[] = {
++ { ".lzma", "" },
++ { ".tlz", ".tar" },
++ { NULL, NULL }
++};
++
++/* Sorry, I just happen to like enumerations. */
++enum PROGRAM_MODE {
++ PM_COMPRESS = 0,
++ PM_DECOMPRESS,
++ PM_TEST,
++ PM_HELP,
++ PM_LICENSE,
++ PM_VERSION
++};
++
++enum {
++ STATUS_OK = 0,
++ STATUS_ERROR = 1,
++ STATUS_WARNING = 2
++};
++
++/* getopt options. */
++/* struct option { name, has_arg, flag, val } */
++const struct option long_options[] = {
++ { "stdout", 0, 0, 'c' },
++ { "decompress", 0, 0, 'd' },
++ { "compress", 0, 0, 'z' },
++ { "keep", 0, 0, 'k' },
++ { "force", 0, 0, 'f' },
++ { "test", 0, 0, 't' },
++ { "suffix", 1, 0, 'S' },
++ { "quiet", 0, 0, 'q' },
++ { "verbose", 0, 0, 'v' },
++ { "help", 0, 0, 'h' },
++ { "license", 0, 0, 'L' },
++ { "version", 0, 0, 'V' },
++ { "fast", 0, 0, '1' },
++ { "best", 0, 0, '9' },
++ { 0, 0, 0, 0 }
++};
++
++/* getopt option string (for the above options). */
++const char option_string[] = "cdzkftS:qvhLV123456789A:D:F:";
++
++/* Defaults. */
++PROGRAM_MODE program_mode = PM_COMPRESS;
++int verbosity = 0;
++bool stdinput = false;
++bool stdoutput = false;
++bool keep = false;
++bool force = false;
++int compression_mode = 7;
++//char *suffix = strdup(".lzma");
++char *suffix = strdup(known_extensions[0].from);
++lzma_option advanced_options = { -1, -1, -1, NULL, -1, -1, -1 };
++
++void print_help(const char *const argv0)
++{
++ // Help goes to stdout while other messages go to stderr.
++ cout << "\nlzma " << PROGRAM_VERSION
++ << " " << PROGRAM_COPYRIGHT << "\n"
++ "Based on LZMA SDK " << LZMA_SDK_VERSION_STRING << " "
++ << LZMA_SDK_COPYRIGHT_STRING
++ << "\n\nUsage: " << argv0
++ << " [flags and input files in any order]\n"
++" -c --stdout output to standard output\n"
++" -d --decompress force decompression\n"
++" -z --compress force compression\n"
++" -k --keep keep (don't delete) input files\n"
++" -f --force force overwrite of output file and compress links\n"
++" -t --test test compressed file integrity\n"
++" -S .suf --suffix .suf use suffix .suf on compressed files\n"
++" -q --quiet suppress error messages\n"
++" -v --verbose be verbose\n"
++" -h --help print this message\n"
++" -L --license display the license information\n"
++" -V --version display version numbers of LZMA SDK and lzma\n"
++" -1 .. -2 fast compression\n"
++" -3 .. -9 good to excellent compression. -7 is the default.\n"
++" --fast alias for -1\n"
++" --best alias for -9 (usually *not* what you want)\n\n"
++" Memory usage depends a lot on the chosen compression mode -1 .. -9.\n"
++" See the man page lzma(1) for details.\n\n";
++}
++
++void print_license(void)
++{
++ cout << "\n LZMA command line tool " << PROGRAM_VERSION << " - "
++ << PROGRAM_COPYRIGHT
++ << "\n LZMA SDK " << LZMA_SDK_VERSION_STRING << " - "
++ << LZMA_SDK_COPYRIGHT_STRING
++ << "\n This program is a part of the LZMA utils package.\n"
++ " http://tukaani.org/lzma/\n\n"
++" This program is free software; you can redistribute it and/or\n"
++" modify it under the terms of the GNU General Public License\n"
++" as published by the Free Software Foundation; either version 2\n"
++" of the License, or (at your option) any later version.\n"
++"\n"
++" This program is distributed in the hope that it will be useful,\n"
++" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
++" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
++" GNU General Public License for more details.\n"
++"\n";
++}
++
++void print_version(void)
++{
++ cout << "LZMA command line tool " << PROGRAM_VERSION << "\n"
++ << "LZMA SDK " << LZMA_SDK_VERSION_STRING << "\n";
++}
++
++short str2int (const char *str, const int &min, const int &max)
++{
++ int value = -1;
++ char *endptr = NULL;
++ if (str == NULL || str[0] == '\0')
++ throw ArgumentException("Invalid integer option");
++ value = strtol (str, &endptr, 10);
++ if (*endptr != '\0' || value < min || value > max)
++ throw ArgumentException("Invalid integer option");
++ return value;
++}
++
++void parse_options(int argc, char **argv, stringVector &filenames)
++{
++ /* Snatched from getopt(3). */
++ int c;
++
++ /* Check how we were called */
++ {
++ char *p = strrchr (argv[0], '/'); // Remove path prefix, if any
++ if (p++ == NULL)
++ p = argv[0];
++ if (strstr (p, "un") != NULL) {
++ program_mode = PM_DECOMPRESS;
++ } else if (strstr (p, "cat") != NULL) {
++ program_mode = PM_DECOMPRESS;
++ stdoutput = true;
++ }
++ }
++
++ while (-1 != (c = getopt_long(argc, argv, option_string,
++ long_options, NULL))) {
++ switch (c) {
++ // stdout
++ case 'c':
++ stdoutput = true;
++ break;
++
++ // decompress
++ case 'd':
++ program_mode = PM_DECOMPRESS;
++ break;
++
++ // compress
++ case 'z':
++ program_mode = PM_COMPRESS;
++ break;
++
++ // keep
++ case 'k':
++ keep = true;
++ break;
++
++ // force
++ case 'f':
++ force = true;
++ break;
++
++ // test
++ case 't':
++ program_mode = PM_TEST;
++ break;
++
++ // suffix
++ case 'S':
++ if (optarg) {
++ free(suffix);
++ suffix = strdup(optarg);
++ }
++ break;
++
++ // quiet
++ case 'q':
++ verbosity = 0;
++ break;
++
++ // verbose
++ case 'v':
++ verbosity++;
++ break;
++
++ // help
++ case 'h':
++ program_mode = PM_HELP;
++ break;
++
++ // license
++ case 'L':
++ program_mode = PM_LICENSE;
++ break;
++
++ // version
++ case 'V':
++ program_mode = PM_VERSION;
++ break;
++
++ case '1': case '2': case '3': case '4': case '5':
++ case '6': case '7': case '8': case '9':
++ compression_mode = c - '0';
++ break;
++
++ // Advanced options //
++ // Compression mode
++ case 'A':
++ advanced_options.compression_mode =
++ str2int (optarg, 0, 2);
++ break;
++
++ // Dictionary size
++ case 'D':
++ advanced_options.dictionary =
++ str2int (optarg, 0, 28);
++ break;
++
++ // Fast bytes
++ case 'F':
++ advanced_options.fast_bytes =
++ str2int (optarg, 0, 273);
++ break;
++
++ default:
++ throw ArgumentException("");
++ break;
++ } // switch(c)
++ } // while(1)
++
++ for (int i = optind; i < argc; i++) {
++ if (strcmp("-", argv[i]) == 0)
++ continue;
++ filenames.push_back(argv[i]);
++ }
++} // parse_options
++
++void set_encoder_properties(NCompress::NLzma::CEncoder *encoder,
++ lzma_option &opt)
++{
++ /* Almost verbatim from LzmaAlone.cpp. */
++ PROPID propIDs[] =
++ {
++ NCoderPropID::kDictionarySize,
++ NCoderPropID::kPosStateBits,
++ NCoderPropID::kLitContextBits,
++ NCoderPropID::kLitPosBits,
++ NCoderPropID::kAlgorithm,
++ NCoderPropID::kNumFastBytes,
++ NCoderPropID::kMatchFinder,
++ NCoderPropID::kEndMarker
++ };
++ const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
++#define VALUE(x) (advanced_options.x >= 0 ? advanced_options.x : opt.x)
++ PROPVARIANT properties[kNumProps];
++ for (int p = 0; p < 6; p++)
++ properties[p].vt = VT_UI4;
++ properties[0].ulVal = UInt32(1 << VALUE (dictionary));
++ properties[1].ulVal = UInt32(VALUE (pos_bits));
++ properties[2].ulVal = UInt32(VALUE (literal_context_bits));
++ properties[3].ulVal = UInt32(VALUE (literal_pos_bits));
++ properties[4].ulVal = UInt32(VALUE (compression_mode));
++ properties[5].ulVal = UInt32(VALUE (fast_bytes));
++#undef VALUE
++
++ properties[6].vt = VT_BSTR;
++ properties[6].bstrVal = (BSTR)opt.match_finder;
++
++ properties[7].vt = VT_BOOL;
++ properties[7].boolVal = stdinput ? VARIANT_TRUE : VARIANT_FALSE;
++
++ if (encoder->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
++ throw Exception("SetCoderProperties() error");
++}
++
++void encode(NCompress::NLzma::CEncoder *encoderSpec,
++ CMyComPtr<ISequentialInStream> inStream,
++ CMyComPtr<ISequentialOutStream> outStream,
++ lzma_option encoder_options,
++ UInt64 fileSize)
++{
++ set_encoder_properties(encoderSpec, encoder_options);
++
++ encoderSpec->WriteCoderProperties(outStream);
++
++ for (int i = 0; i < 8; i++)
++ {
++ Byte b = Byte(fileSize >> (8 * i));
++ if (outStream->Write(&b, sizeof(b), 0) != S_OK)
++ throw Exception("Write error while encoding");
++ }
++
++ HRESULT result = encoderSpec->Code(inStream, outStream, 0, 0, 0);
++
++ if (result == E_OUTOFMEMORY)
++ throw Exception("Cannot allocate memory");
++ else if (result != S_OK) {
++ char buffer[33];
++ snprintf(buffer, 33, "%d", (unsigned int)result);
++ throw Exception(string("Encoder error: ") + buffer);
++ }
++}
++
++void decode(NCompress::NLzma::CDecoder *decoderSpec,
++ CMyComPtr<ISequentialInStream> inStream,
++ CMyComPtr<ISequentialOutStream> outStream)
++{
++ const UInt32 kPropertiesSize = 5;
++ Byte properties[kPropertiesSize];
++ UInt32 processedSize;
++ UInt64 fileSize = 0;
++
++ if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK)
++ throw Exception("Read error");
++ if (processedSize != kPropertiesSize)
++ throw Exception("Read error");
++ if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
++ throw Exception("SetDecoderProperties() error");
++
++ for (int i = 0; i < 8; i++)
++ {
++ Byte b;
++
++ if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK)
++ throw Exception("Read error");
++ if (processedSize != 1)
++ throw Exception("Read error");
++
++ fileSize |= ((UInt64)b) << (8 * i);
++ }
++
++ if (decoderSpec->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
++ throw Exception("Decoder error");
++}
++
++int open_instream(const string infile,
++ CMyComPtr<ISequentialInStream> &inStream,
++ UInt64 &fileSize)
++{
++ CInFileStream *inStreamSpec = new CInFileStream;
++ inStream = inStreamSpec;
++ if (!inStreamSpec->Open(infile.c_str()))
++ throw Exception("Cannot open input file " + infile);
++
++ inStreamSpec->File.GetLength(fileSize);
++
++ return inStreamSpec->File.GetHandle();
++}
++
++int open_outstream(const string outfile,
++ CMyComPtr<ISequentialOutStream> &outStream)
++{
++ COutFileStream *outStreamSpec = new COutFileStream;
++ outStream = outStreamSpec;
++
++ bool open_by_force = (program_mode == PM_TEST) | force;
++
++ if (!outStreamSpec->Create(outfile.c_str(), open_by_force))
++ throw Exception("Cannot open output file " + outfile);
++
++ return outStreamSpec->File.GetHandle();
++}
++
++double get_ratio(int inhandle, int outhandle)
++{
++ struct stat in_stats, out_stats;
++ fstat(inhandle, &in_stats);
++ fstat(outhandle, &out_stats);
++
++ return (double)out_stats.st_size / (double)in_stats.st_size;
++}
++
++mode_t get_file_mode(string filename)
++{
++ struct stat in_stat;
++ lstat(filename.c_str(), &in_stat);
++
++ return in_stat.st_mode;
++}
++
++bool string_ends_with(string str, string ending)
++{
++ return equal(ending.rbegin(), ending.rend(), str.rbegin());
++}
++
++bool extension_is_known(string filename)
++{
++ bool known_format = false;
++ extension_pair extension; int i = 1;
++
++ extension = known_extensions[0];
++ while (extension.from != NULL) {
++ if (string_ends_with(filename, extension.from)) {
++ known_format = true;
++ break;
++ }
++ extension = known_extensions[i];
++ i++;
++ }
++
++ if (!known_format) {
++ if (!string_ends_with(filename, suffix)) {
++ return false;
++ }
++ }
++
++ return true;
++}
++
++string replace_extension(string filename)
++{
++ int suffix_starts_at = filename.length() - strlen (suffix);
++ string from_suffix = filename.substr(suffix_starts_at, strlen (suffix));
++ string ret = filename.substr(0, suffix_starts_at);
++ extension_pair extension; int i = 1;
++
++ bool found_replacement = false;
++ extension = known_extensions[0];
++ while (extension.from != NULL) {
++ if (from_suffix.compare(extension.from) == 0) {
++ ret += extension.to;
++ found_replacement = true;
++ break;
++ }
++
++ extension = known_extensions[i];
++ i++;
++ }
++
++ return ret;
++}
++
++string pretty_print_status(string filename, string output_filename,
++ string ratio)
++{
++ string ret = "";
++
++ ret += filename;
++ ret += ":\t ";
++
++ if (program_mode == PM_TEST) {
++ ret += "decoded succesfully";
++
++ return ret;
++ }
++
++ if (!stdinput && !stdoutput) {
++ ret += ratio;
++ ret += " -- ";
++ }
++
++ if (program_mode == PM_COMPRESS) {
++ if (keep) {
++ ret += "encoded succesfully";
++
++ return ret;
++ }
++
++ ret += "replaced with ";
++ ret += output_filename;
++
++ return ret;
++ }
++
++ if (program_mode == PM_DECOMPRESS) {
++ if (keep) {
++ ret += "decoded succesfully";
++
++ return ret;
++ }
++
++ ret += "replaced with ";
++ ret += output_filename;
++
++ return ret;
++ }
++
++ return ret;
++}
++
++static string archive_name; // I know, it is crude, but I haven't found any other
++ // way then making a global variable to transfer filename to handler
++
++void signal_handler (int signum)
++{
++ unlink (archive_name.c_str()); // deleting
++ signal (signum, SIG_DFL); // we return the default function to used signal
++ kill (getpid(), signum); // and then send this signal to the process again
++}
++
++} // namespace lzma
++
++
++int main(int argc, char **argv)
++{
++ using namespace lzma;
++ using std::cerr;
++
++ stringVector filenames;
++
++ signal (SIGTERM,signal_handler);
++ signal (SIGHUP,signal_handler);
++ signal (SIGINT,signal_handler);
++
++ try {
++ parse_options(argc, argv, filenames);
++ }
++ catch (...) {
++ return STATUS_ERROR;
++ }
++
++ if (program_mode == PM_HELP) {
++ print_help(argv[0]);
++ return STATUS_OK;
++ }
++ else if (program_mode == PM_LICENSE) {
++ print_license();
++ return STATUS_OK;
++ }
++ else if (program_mode == PM_VERSION) {
++ print_version();
++ return STATUS_OK;
++ }
++
++ if (filenames.empty()) {
++ stdinput = true;
++ stdoutput = true;
++
++ /* FIXME: get rid of this */
++ filenames.push_back("-");
++ }
++
++ /* Protection: always create new files with 0600 in order to prevent
++ * outsiders from reading incomplete data. */
++ umask(0077);
++
++ bool warning = false;
++
++ for (int i = 0; i < filenames.size(); i++) {
++ CMyComPtr<ISequentialInStream> inStream;
++ CMyComPtr<ISequentialOutStream> outStream;
++ UInt64 fileSize = 0;
++ int inhandle = 0, outhandle = 0;
++ string output_filename;
++
++ if (stdinput) {
++ inStream = new CStdInFileStream;
++ MY_SET_BINARY_MODE(stdin);
++ fileSize = (UInt64)(Int64)-1;
++
++ inhandle = STDIN_FILENO;
++
++ outStream = new CStdOutFileStream;
++ MY_SET_BINARY_MODE(stdout);
++
++ outhandle = STDOUT_FILENO;
++ }
++ else {
++ mode_t infile_mode = get_file_mode(filenames[i]);
++ if (!S_ISREG(infile_mode)) {
++ if (S_ISDIR(infile_mode)) {
++ warning = true;
++ cerr << argv[0] << ": " << filenames[i] << ": "
++ << "cowardly refusing to work on directory"
++ << endl;
++
++ continue;
++ }
++ else if (S_ISLNK(infile_mode)) {
++ if (!stdoutput && !force) {
++ warning = true;
++
++ cerr << argv[0] << ": " << filenames[i] << ": "
++ << "cowardly refusing to work on symbolic link "
++ << "(use --force to force encoding or decoding)"
++ << endl;
++
++ continue;
++ }
++ }
++ else {
++ warning = true;
++
++ cerr << argv[0] << ": " << filenames[i] << ": "
++ << "doesn't exist or is not a regular file"
++ << endl;
++
++ continue;
++ }
++ }
++
++ // Test if the file already ends with *suffix.
++ if (program_mode == PM_COMPRESS && !force
++ && string_ends_with(filenames[i],
++ suffix)) {
++ warning = true;
++
++ cerr << filenames[i] << " already has "
++ << suffix << " suffix -- unchanged\n";
++
++ continue;
++ }
++
++ // Test if the file extension is known.
++ if (program_mode == PM_DECOMPRESS
++ && !extension_is_known(filenames[i])) {
++ warning = true;
++
++ cerr << filenames[i] << ": "
++ << " unknown suffix -- unchanged"
++ << endl;
++
++ continue;
++ }
++
++ try {
++ inhandle = open_instream(filenames[i], inStream, fileSize);
++ }
++ catch (Exception e) {
++ cerr << argv[0] << ": " << e.what() << endl;
++ return STATUS_ERROR;
++ }
++
++ if (stdoutput) {
++ outStream = new CStdOutFileStream;
++ MY_SET_BINARY_MODE(stdout);
++
++ outhandle = STDOUT_FILENO;
++ }
++ else {
++ /* Testing mode is nothing else but decoding
++ * and throwing away the result. */
++ if (program_mode == PM_TEST)
++ output_filename = "/dev/null";
++ else if (program_mode == PM_DECOMPRESS)
++ output_filename = replace_extension(filenames[i]);
++ else
++ output_filename = filenames[i]
++ + suffix;
++ archive_name = output_filename;
++
++ try {
++ outhandle = open_outstream(output_filename, outStream);
++ }
++ catch (Exception e) {
++ cerr << argv[0] << ": " << e.what() << endl;
++ return STATUS_ERROR;
++ }
++ }
++
++ }
++
++ // Unless --force is specified, do not read/write compressed
++ // data from/to a terminal.
++ if (!force) {
++ if (program_mode == PM_COMPRESS && isatty(outhandle)) {
++ cerr << argv[0] << ": compressed data not "
++ "written to a terminal. Use "
++ "-f to force compression.\n"
++ << argv[0] << ": For help, type: "
++ << argv[0] << " -h\n";
++ return STATUS_ERROR;
++ } else if (program_mode == PM_DECOMPRESS
++ && isatty(inhandle)) {
++ cerr << argv[0] << ": compressed data not "
++ "read from a terminal. Use "
++ "-f to force decompression.\n"
++ << argv[0] << ": For help, type: "
++ << argv[0] << " -h\n";
++ return STATUS_ERROR;
++ }
++ }
++
++ if (program_mode == PM_COMPRESS) {
++ NCompress::NLzma::CEncoder *encoderSpec =
++ new NCompress::NLzma::CEncoder;
++
++ lzma_option options = option_mapping[compression_mode];
++
++ try {
++ encode(encoderSpec, inStream, outStream, options, fileSize);
++ }
++ catch (Exception e) {
++ cerr << argv[0] << ": " << e.what() << endl;
++ unlink(output_filename.c_str());
++ delete(encoderSpec);
++
++ return STATUS_ERROR;
++ }
++
++ delete(encoderSpec);
++ }
++ else { // PM_DECOMPRESS | PM_TEST
++ NCompress::NLzma::CDecoder *decoderSpec =
++ new NCompress::NLzma::CDecoder;
++
++ try {
++ decode(decoderSpec, inStream, outStream);
++ }
++ catch (Exception e) {
++ cerr << argv[0] << ": " << e.what() << endl;
++ unlink(output_filename.c_str());
++ delete(decoderSpec);
++
++ return STATUS_ERROR;
++ }
++
++ delete(decoderSpec);
++ }
++
++ /* Set permissions and owners. */
++ if ( (program_mode == PM_COMPRESS || program_mode == PM_DECOMPRESS )
++ && (!stdinput && !stdoutput) ) {
++
++ int ret = 0;
++ struct stat file_stats;
++ ret = fstat(inhandle, &file_stats);
++
++ ret = fchmod(outhandle, file_stats.st_mode);
++ ret = fchown(outhandle, file_stats.st_uid, file_stats.st_gid);
++ // We need to call fchmod() again, since otherwise the SUID bits
++ // are lost.
++ ret = fchmod(outhandle, file_stats.st_mode);
++
++ struct timeval file_times[2];
++ // Access time
++ file_times[0].tv_sec = file_stats.st_atime;
++ file_times[0].tv_usec = 0;
++ // Modification time
++ file_times[1].tv_sec = file_stats.st_mtime;
++ file_times[1].tv_usec = 0;
++
++ ret = futimes(outhandle, file_times);
++
++ if (!keep)
++ unlink(filenames[i].c_str());
++ }
++
++ if (verbosity > 0) {
++ if (stdoutput) {
++ cerr << filenames[i] << ":\t ";
++ cerr << "decoded succesfully"
++ << endl;
++ }
++
++ else {
++ char buf[10] = { 0 };
++
++ if (program_mode == PM_DECOMPRESS)
++ snprintf(buf, 10, "%.2f%%",
++ (1 - get_ratio(outhandle, inhandle)) * 100);
++ if (program_mode == PM_COMPRESS)
++ snprintf(buf, 10, "%.2f%%",
++ (1 - get_ratio(inhandle, outhandle)) * 100);
++
++ string ratio = buf;
++ cerr << pretty_print_status(filenames[i], output_filename,
++ ratio)
++ << endl;
++ }
++ }
++ }
++
++ if (warning)
++ return STATUS_WARNING;
++
++ return STATUS_OK;
++}
++
+Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/Exception.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/Exception.h 2009-06-01 22:01:10.000000000 +0200
+@@ -0,0 +1,45 @@
++/* A couple of exceptions for lzmp.
++ *
++ * Copyright (C) 2005 Ville Koskinen
++ *
++ * 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.
++ */
++
++#ifndef _EXCEPTION_H_
++#define _EXCEPTION_H_
++
++#include <string>
++using std::string;
++
++class Exception
++{
++private:
++ string message;
++public:
++ Exception(char *what): message(what) { }
++ Exception(string what): message(what) { }
++
++ ~Exception() { }
++
++ string what(void) { return message; }
++};
++
++class ArgumentException: public Exception
++{
++public:
++ ArgumentException(char *what): Exception(what) { }
++ ArgumentException(string what): Exception(what) { }
++
++ ~ArgumentException() { }
++};
++
++#endif
++
+Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
+===================================================================
+--- lzma-4.65.orig/CPP/7zip/Compress/LZMA_Alone/makefile.gcc 2009-06-01 22:00:54.000000000 +0200
++++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc 2009-06-01 22:06:13.000000000 +0200
+@@ -1,9 +1,10 @@
+-PROG = lzma
++PROG = lzma_alone
++PROG2 = lzma
+ CXX = g++ -O2 -Wall
+ CXX_C = gcc -O2 -Wall
+ LIB = -lm
+ RM = rm -f
+-CFLAGS = -c -D_FILE_OFFSET_BITS=64
++CFLAGS = -c -I ../../../ -D_FILE_OFFSET_BITS=64 -DPACKAGE_VERSION="\"4.32.0beta3\""
+
+ ifdef SystemDrive
+ IS_MINGW = 1
+@@ -45,12 +46,35 @@
+ Lzma86Dec.o \
+ Lzma86Enc.o \
+
++OBJS2 = \
++ C_FileIO.o \
++ CRC.o \
++ Alloc.o \
++ FileStreams.o \
++ StreamUtils.o \
++ InBuffer.o \
++ OutBuffer.o \
++ LzmaDecoder.o \
++ StringConvert.o \
++ StringToInt.o \
++ LzmaEncoder.o \
++ LzmaDec.o \
++ LzmaEnc.o \
++ LzFind.o \
++ 7zCrc.o \
++ lzmp.o
+
+-all: $(PROG)
++all: $(PROG) $(PROG2)
+
+ $(PROG): $(OBJS)
+ $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
+
++$(PROG2): $(OBJS2)
++ $(CXX) -o $(PROG2) $(LDFLAGS) $(OBJS2) $(LIB)
++
++lzmp.o: lzmp.cpp
++ $(CXX) $(CFLAGS) lzmp.cpp
++
+ LzmaAlone.o: LzmaAlone.cpp
+ $(CXX) $(CFLAGS) LzmaAlone.cpp
+
+@@ -131,5 +153,5 @@
+ $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c
+
+ clean:
+- -$(RM) $(PROG) $(OBJS)
++ -$(RM) $(PROG) $(PROG2) $(OBJS)
+
+Index: lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzma_version.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzma_version.h 2009-06-01 22:01:10.000000000 +0200
+@@ -0,0 +1,31 @@
++#ifndef LZMA_VERSION_H
++#define LZMA_VERSION_H
++
++/*
++ Version and copyright information used by LZMA utils.
++*/
++
++static const char *LZMA_SDK_VERSION_STRING = "4.43";
++
++static const char *LZMA_SDK_COPYRIGHT_STRING =
++ "Copyright (C) 1999-2006 Igor Pavlov";
++
++static const char *LZMA_SDK_COPYRIGHT_INFO =
++ " See http://7-zip.org/sdk.html or the documentation of LZMA SDK for\n"
++ " the license. For reference, the version 4.43 is free software\n"
++ " licensed under the GNU LGPL.";
++
++
++static const char *LZMA_UTILS_VERSION_STRING = PACKAGE_VERSION;
++
++static const char *LZMA_UTILS_COPYRIGHT_STRING =
++ "Copyright (C) 2006 Lasse Collin";
++
++static const char *LZMA_UTILS_COPYRIGHT_INFO =
++ "This program comes with ABSOLUTELY NO WARRANTY.\n"
++ "You may redistribute copies of this program\n"
++ "under the terms of the GNU General Public License.\n"
++ "For more information about these matters, see the file "
++ "named COPYING.\n";
++
++#endif /* ifndef LZMA_VERSION_H */
+Index: lzma-4.65/CPP/Common/C_FileIO.h
+===================================================================
+--- lzma-4.65.orig/CPP/Common/C_FileIO.h 2009-05-15 23:33:51.000000000 +0200
++++ lzma-4.65/CPP/Common/C_FileIO.h 2009-06-01 22:06:56.000000000 +0200
+@@ -24,6 +24,7 @@
+ bool Close();
+ bool GetLength(UInt64 &length) const;
+ off_t Seek(off_t distanceToMove, int moveMethod) const;
++ int GetHandle() const { return _handle; }
+ };
+
+ class CInFile: public CFileBase
diff --git a/tools/lzma/patches/003-compile_fixes.patch b/tools/lzma/patches/003-compile_fixes.patch
new file mode 100644
index 0000000..49ae66b
--- /dev/null
+++ b/tools/lzma/patches/003-compile_fixes.patch
@@ -0,0 +1,26 @@
+diff -urN lzma-4.65/CPP/7zip/Common/FileStreams.h lzma-4.65.new/CPP/7zip/Common/FileStreams.h
+--- lzma-4.65/CPP/7zip/Common/FileStreams.h 2009-05-15 23:33:51.000000000 +0200
++++ lzma-4.65.new/CPP/7zip/Common/FileStreams.h 2009-06-01 22:30:01.000000000 +0200
+@@ -72,6 +72,7 @@
+ public IOutStream,
+ public CMyUnknownImp
+ {
++public:
+ #ifdef USE_WIN_FILE
+ NWindows::NFile::NIO::COutFile File;
+ #else
+diff -urN lzma-4.65/CPP/Common/MyWindows.h lzma-4.65.new/CPP/Common/MyWindows.h
+--- lzma-4.65/CPP/Common/MyWindows.h 2009-05-15 23:33:51.000000000 +0200
++++ lzma-4.65.new/CPP/Common/MyWindows.h 2009-06-01 22:29:26.000000000 +0200
+@@ -101,8 +101,11 @@
+
+ #ifdef __cplusplus
+
++#ifndef INITGUID
++#define INITGUID
+ DEFINE_GUID(IID_IUnknown,
+ 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
++#endif
+ struct IUnknown
+ {
+ STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;
diff --git a/tools/lzma/patches/100-static_library.patch b/tools/lzma/patches/100-static_library.patch
new file mode 100644
index 0000000..15ab4e0
--- /dev/null
+++ b/tools/lzma/patches/100-static_library.patch
@@ -0,0 +1,70 @@
+--- a/C/LzmaUtil/makefile.gcc
++++ b/C/LzmaUtil/makefile.gcc
+@@ -1,44 +1,53 @@
+ PROG = lzma
+-CXX = g++
+-LIB =
++CC = gcc
++LIB = liblzma.a
+ RM = rm -f
+ CFLAGS = -c -O2 -Wall
++AR = ar
++RANLIB = ranlib
+
+ OBJS = \
+- LzmaUtil.o \
+ Alloc.o \
+ LzFind.o \
+ LzmaDec.o \
+ LzmaEnc.o \
++ LzmaLib.o \
+ 7zFile.o \
+ 7zStream.o \
+
+-
+ all: $(PROG)
+
+-$(PROG): $(OBJS)
+- $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
++$(PROG): LzmaUtil.o $(LIB)
++ $(CC) -o $(PROG) $(LDFLAGS) $< $(LIB)
+
+ LzmaUtil.o: LzmaUtil.c
+- $(CXX) $(CFLAGS) LzmaUtil.c
++ $(CC) $(CFLAGS) LzmaUtil.c
++
++$(LIB): $(OBJS)
++ rm -f $@
++ $(AR) rcu $@ $(OBJS)
++ $(RANLIB) $@
+
+ Alloc.o: ../Alloc.c
+- $(CXX) $(CFLAGS) ../Alloc.c
++ $(CC) $(CFLAGS) ../Alloc.c
+
+ LzFind.o: ../LzFind.c
+- $(CXX) $(CFLAGS) ../LzFind.c
++ $(CC) $(CFLAGS) ../LzFind.c
+
+ LzmaDec.o: ../LzmaDec.c
+- $(CXX) $(CFLAGS) ../LzmaDec.c
++ $(CC) $(CFLAGS) ../LzmaDec.c
+
+ LzmaEnc.o: ../LzmaEnc.c
+- $(CXX) $(CFLAGS) ../LzmaEnc.c
++ $(CC) $(CFLAGS) ../LzmaEnc.c
++
++LzmaLib.o: ../LzmaLib.c
++ $(CC) $(CFLAGS) ../LzmaLib.c
+
+ 7zFile.o: ../7zFile.c
+- $(CXX) $(CFLAGS) ../7zFile.c
++ $(CC) $(CFLAGS) ../7zFile.c
+
+ 7zStream.o: ../7zStream.c
+- $(CXX) $(CFLAGS) ../7zStream.c
++ $(CC) $(CFLAGS) ../7zStream.c
+
+ clean:
+- -$(RM) $(PROG) $(OBJS)
++ -$(RM) $(PROG) *.o *.a
diff --git a/tools/m4/Makefile b/tools/m4/Makefile
new file mode 100644
index 0000000..47c3321
--- /dev/null
+++ b/tools/m4/Makefile
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2008-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=m4
+PKG_VERSION:=1.4.17
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=12a3c829301a4fd6586a57d3fcf196dc
+PKG_CAT:=xzcat
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_VARS += gl_cv_func_strstr_linear=no
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/m4/patches/100-fix-gets-removal.patch b/tools/m4/patches/100-fix-gets-removal.patch
new file mode 100644
index 0000000..ecd110d
--- /dev/null
+++ b/tools/m4/patches/100-fix-gets-removal.patch
@@ -0,0 +1,17 @@
+--- a/lib/stdio.in.h
++++ b/lib/stdio.in.h
+@@ -714,14 +714,6 @@ _GL_WARN_ON_USE (getline, "getline is un
+ # endif
+ #endif
+
+-/* It is very rare that the developer ever has full control of stdin,
+- so any use of gets warrants an unconditional warning; besides, C11
+- removed it. */
+-#undef gets
+-#if HAVE_RAW_DECL_GETS
+-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
+-#endif
+-
+
+ #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
+ struct obstack;
diff --git a/tools/make-ext4fs/Makefile b/tools/make-ext4fs/Makefile
new file mode 100644
index 0000000..d6858cd
--- /dev/null
+++ b/tools/make-ext4fs/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=make-ext4fs
+PKG_VERSION:=2015-09-14
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://git.openwrt.org/project/make_ext4fs.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=98e3d5c1ceddd4a32b92c1cfafe929fe006fb98c
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_MIRROR_MD5SUM:=c736e546de3b36da73f5e84a9ce3ffee
+PKG_CAT:=zcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+ifeq ($(HOST_OS),Linux)
+ MAKE_STATIC := STATIC=1
+endif
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) make_ext4fs $(MAKE_STATIC)
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/make_ext4fs $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/make_ext4fs
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/missing-macros/Makefile b/tools/missing-macros/Makefile
new file mode 100644
index 0000000..e4b69b3
--- /dev/null
+++ b/tools/missing-macros/Makefile
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2010-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=missing-macros
+PKG_VERSION:=10
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Configure
+endef
+
+define Host/Compile
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/share/aclocal
+ $(INSTALL_DATA) ./src/m4/*.m4 $(STAGING_DIR_HOST)/share/aclocal/
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) ./src/bin/* $(STAGING_DIR_HOST)/bin/
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/missing-macros/src/README b/tools/missing-macros/src/README
new file mode 100644
index 0000000..d2305ff
--- /dev/null
+++ b/tools/missing-macros/src/README
@@ -0,0 +1,100 @@
+The m4/ directory below contains various m4 macros used
+by different packages in the OpenWrt feed.
+
+
+From GNU gettext:
+Library linking and rpath helper macros.
+
+ lib-ld.m4
+ lib-link.m4
+ lib-prefix.m4
+
+Integer data type test macros.
+
+ intmax.m4
+ wint_t.m4
+ inttypes-pri.m4
+ uintmax_t.m4
+ stdint_h.m4
+ intdiv0.m4
+ inttypes_h.m4
+
+Program test macro.
+
+ progtest.m4
+
+GNU libc version test macros.
+
+ glibc2.m4
+ glibc21.m4
+
+
+From UCL and LZO:
+Compiler ACC conformance testing macros.
+
+ mfx_acc.m4
+ mfx_cppflags.m4
+ mfx_limits.m4
+
+
+From OSSP-JS:
+Test macros for va_copy() implementations.
+
+ va_copy.m4
+
+
+From libmikmod:
+Feature test macros for the Enlightment Sound Daemon.
+
+ esd.m4
+
+
+From libdnet:
+Feature test macros for socket api implementations.
+
+ dnet.m4
+
+
+From FLAC:
+XMMS feature detection macros.
+
+ xmms.m4
+
+
+From ao:
+Directory expansion macro for Automake.
+
+ as-ac-expand.m4
+
+
+From tinyproxy:
+Autostars m4 macro for detection of compiler flags.
+
+ as-compiler-flags.m4
+
+
+From morituri:
+Autostars m4 macro for versioning.
+
+ as-version.m4
+
+
+From liboil:
+Check if unaligned memory access works correctly.
+
+ as-unaligned-access.m4
+
+
+From OpenWrt:
+Always disable GTK docs.
+
+ fake-gtk-doc-check.m4
+
+Provide intltool.m4 stubs to allow for autoreconf.
+
+ fake-intltool.m4
+
+From XDM:
+XAW macros.
+
+ xaw.m4
diff --git a/tools/missing-macros/src/bin/help2man b/tools/missing-macros/src/bin/help2man
new file mode 100755
index 0000000..6cbec57
--- /dev/null
+++ b/tools/missing-macros/src/bin/help2man
@@ -0,0 +1,29 @@
+#!/usr/bin/env perl
+
+use strict;
+use Getopt::Long;
+
+my $output;
+my $version;
+
+Getopt::Long::Configure('pass_through');
+Getopt::Long::GetOptions(
+ 'output=s' => \$output,
+ 'version' => \$version
+);
+
+if ($version)
+{
+ printf "OpenWrt help2man 1.40.10\n";
+ exit 0;
+}
+elsif ($output)
+{
+ open O, "> $output" || die "Unable to open $output: $!\n";
+ print O "Dummy man page.\n";
+ close O;
+}
+else
+{
+ print O "Dummy man page.\n";
+}
diff --git a/tools/missing-macros/src/bin/makeinfo b/tools/missing-macros/src/bin/makeinfo
new file mode 100755
index 0000000..e163cba
--- /dev/null
+++ b/tools/missing-macros/src/bin/makeinfo
@@ -0,0 +1,112 @@
+#!/usr/bin/env perl
+
+use strict;
+use Getopt::Long;
+
+my $output;
+my $version;
+my $docbook;
+my $html;
+my $xml;
+my $plaintext;
+my $no_split;
+my $no_headers;
+
+Getopt::Long::Configure('pass_through');
+Getopt::Long::GetOptions(
+ 'output=s' => \$output,
+ 'version' => \$version,
+ 'no-split' => \$no_split,
+ 'no-headers' => \$no_headers,
+ 'docbook' => \$docbook,
+ 'html' => \$html,
+ 'xml' => \$xml,
+ 'plaintext' => \$plaintext
+);
+
+if ($version)
+{
+ print "makeinfo (OpenWrt stub) 4.13\n";
+ exit 0;
+}
+
+
+sub output_filename
+{
+ my $path = shift || return;
+ my $name = $path;
+ my $setfile;
+
+ if (open F, "< $path")
+ {
+ while (defined(my $line = readline F))
+ {
+ if ($line =~ /\@setfilename\s+(\S+)/)
+ {
+ $setfile = $1;
+ $setfile =~ s!^.+/!!;
+ last;
+ }
+ }
+
+ close F;
+ }
+
+ $name =~ s!^.+/!!;
+ $name =~ s!\.[^.]+$!!;
+
+ if ($html)
+ {
+ $setfile =~ s!\.[^.]+$!! if $setfile;
+
+ if ($no_split)
+ {
+ return $setfile ? "$setfile.html" : "$name.html" unless $output;
+ return $output;
+ }
+
+ return $setfile ? "$setfile/index.html" : "$name/index.html" unless $output;
+ return "$output/index.html";
+ }
+ elsif ($xml || $docbook)
+ {
+ $setfile =~ s!\.[^.]+$!! if $setfile;
+
+ return $setfile ? "$setfile.xml" : "$name.info" unless $output;
+ return $output;
+ }
+ elsif ($plaintext)
+ {
+ return ($output || "-");
+ }
+
+ return ($output || $setfile || "$name.info");
+}
+
+foreach my $arg (@ARGV)
+{
+ next unless -f $arg;
+
+ my $out = output_filename($arg);
+ if ($out =~ m!^(.+/)[^/]+$!)
+ {
+ system("mkdir", "-p", $1);
+ }
+
+ my $fd = \*STDOUT;
+ if ($out ne "-" && !$no_headers)
+ {
+ open $fd, "> $out" || die "Can't open $out: $!\n";
+ }
+
+ if ($html || $xml || $docbook)
+ {
+ print $fd "<!-- Dummy output for $arg -->\n";
+ }
+ else
+ {
+ print $fd "Dummy output for $arg\n";
+ }
+
+ close $fd;
+}
diff --git a/tools/missing-macros/src/m4/as-ac-expand.m4 b/tools/missing-macros/src/m4/as-ac-expand.m4
new file mode 100644
index 0000000..d6c9e33
--- /dev/null
+++ b/tools/missing-macros/src/m4/as-ac-expand.m4
@@ -0,0 +1,43 @@
+dnl as-ac-expand.m4 0.2.0
+dnl autostars m4 macro for expanding directories using configure's prefix
+dnl thomas@apestaart.org
+
+dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
+dnl example
+dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
+dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
+
+AC_DEFUN([AS_AC_EXPAND],
+[
+ EXP_VAR=[$1]
+ FROM_VAR=[$2]
+
+ dnl first expand prefix and exec_prefix if necessary
+ prefix_save=$prefix
+ exec_prefix_save=$exec_prefix
+
+ dnl if no prefix given, then use /usr/local, the default prefix
+ if test "x$prefix" = "xNONE"; then
+ prefix="$ac_default_prefix"
+ fi
+ dnl if no exec_prefix given, then use prefix
+ if test "x$exec_prefix" = "xNONE"; then
+ exec_prefix=$prefix
+ fi
+
+ full_var="$FROM_VAR"
+ dnl loop until it doesn't change anymore
+ while true; do
+ new_full_var="`eval echo $full_var`"
+ if test "x$new_full_var" = "x$full_var"; then break; fi
+ full_var=$new_full_var
+ done
+
+ dnl clean up
+ full_var=$new_full_var
+ AC_SUBST([$1], "$full_var")
+
+ dnl restore prefix and exec_prefix
+ prefix=$prefix_save
+ exec_prefix=$exec_prefix_save
+])
diff --git a/tools/missing-macros/src/m4/as-compiler-flag.m4 b/tools/missing-macros/src/m4/as-compiler-flag.m4
new file mode 100644
index 0000000..0f660cf
--- /dev/null
+++ b/tools/missing-macros/src/m4/as-compiler-flag.m4
@@ -0,0 +1,62 @@
+dnl as-compiler-flag.m4 0.1.0
+
+dnl autostars m4 macro for detection of compiler flags
+
+dnl David Schleef <ds@schleef.org>
+
+dnl $Id: as-compiler-flag.m4,v 1.1 2005/12/15 23:35:19 ds Exp $
+
+dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_COMPILER_FLAG],
+[
+ AC_MSG_CHECKING([to see if compiler understands $1])
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+
+ AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ m4_ifvaln([$2],[$2])
+ true
+ else
+ m4_ifvaln([$3],[$3])
+ true
+ fi
+ AC_MSG_RESULT([$flag_ok])
+])
+
+dnl AS_COMPILER_FLAGS(VAR, FLAGS)
+dnl Tries to compile with the given CFLAGS.
+
+AC_DEFUN([AS_COMPILER_FLAGS],
+[
+ list=$2
+ flags_supported=""
+ flags_unsupported=""
+ AC_MSG_CHECKING([for supported compiler flags])
+ for each in $list
+ do
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $each"
+ AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ flags_supported="$flags_supported $each"
+ else
+ flags_unsupported="$flags_unsupported $each"
+ fi
+ done
+ AC_MSG_RESULT([$flags_supported])
+ if test "X$flags_unsupported" != X ; then
+ AC_MSG_WARN([unsupported compiler flags: $flags_unsupported])
+ fi
+ $1="$$1 $flags_supported"
+])
+
diff --git a/tools/missing-macros/src/m4/as-unaligned-access.m4 b/tools/missing-macros/src/m4/as-unaligned-access.m4
new file mode 100644
index 0000000..ede8bd2
--- /dev/null
+++ b/tools/missing-macros/src/m4/as-unaligned-access.m4
@@ -0,0 +1,41 @@
+dnl AS_UNALIGNED_ACCESS
+
+dnl check if unaligned memory access works correctly
+AC_DEFUN([AS_UNALIGNED_ACCESS], [
+ AC_MSG_CHECKING([if unaligned memory access works correctly])
+ if test x"$as_cv_unaligned_access" = x ; then
+ case $host in
+ alpha*|arm*|hp*|mips*|sh*|sparc*|ia64*)
+ _AS_ECHO_N([(blacklisted) ])
+ as_cv_unaligned_access=no
+ ;;
+ i?86*|x86_64|amd64|powerpc*|m68k*|cris*)
+ _AS_ECHO_N([(whitelisted) ])
+ as_cv_unaligned_access=yes
+ ;;
+ esac
+ else
+ _AS_ECHO_N([(cached) ])
+ fi
+ if test x"$as_cv_unaligned_access" = x ; then
+ AC_TRY_RUN([
+int main(int argc, char **argv)
+{
+ char array[] = "ABCDEFGH";
+ unsigned int iarray[2];
+ memcpy(iarray,array,8);
+#define GET(x) (*(unsigned int *)((char *)iarray + (x)))
+ if(GET(0) != 0x41424344 && GET(0) != 0x44434241) return 1;
+ if(GET(1) != 0x42434445 && GET(1) != 0x45444342) return 1;
+ if(GET(2) != 0x43444546 && GET(2) != 0x46454443) return 1;
+ if(GET(3) != 0x44454647 && GET(3) != 0x47464544) return 1;
+ return 0;
+}
+ ], as_cv_unaligned_access="yes", as_cv_unaligned_access="no")
+ fi
+ AC_MSG_RESULT($as_cv_unaligned_access)
+ if test "$as_cv_unaligned_access" = "yes"; then
+ AC_DEFINE_UNQUOTED(HAVE_UNALIGNED_ACCESS, 1,
+ [defined if unaligned memory access works correctly])
+ fi
+])
diff --git a/tools/missing-macros/src/m4/as-version.m4 b/tools/missing-macros/src/m4/as-version.m4
new file mode 100644
index 0000000..a5b4399
--- /dev/null
+++ b/tools/missing-macros/src/m4/as-version.m4
@@ -0,0 +1,71 @@
+dnl as-version.m4 0.2.0
+
+dnl autostars m4 macro for versioning
+
+dnl Thomas Vander Stichele <thomas at apestaart dot org>
+
+dnl $Id: as-version.m4,v 1.4 2004/06/01 09:40:05 thomasvs Exp $
+
+dnl AS_VERSION
+
+dnl example
+dnl AS_VERSION
+
+dnl this macro
+dnl - AC_SUBST's PACKAGE_VERSION_MAJOR, _MINOR, _MICRO
+dnl - AC_SUBST's PACKAGE_VERSION_RELEASE,
+dnl which can be used for rpm release fields
+dnl - doesn't call AM_INIT_AUTOMAKE anymore because it prevents
+dnl maintainer mode from running correctly
+dnl
+dnl don't forget to put #undef PACKAGE_VERSION_RELEASE in acconfig.h
+dnl if you use acconfig.h
+
+AC_DEFUN([AS_VERSION],
+[
+ PACKAGE_VERSION_MAJOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f1)
+ PACKAGE_VERSION_MINOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f2)
+ PACKAGE_VERSION_MICRO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f3)
+
+ AC_SUBST(PACKAGE_VERSION_MAJOR)
+ AC_SUBST(PACKAGE_VERSION_MINOR)
+ AC_SUBST(PACKAGE_VERSION_MICRO)
+])
+
+dnl AS_NANO(ACTION-IF-NO-NANO, [ACTION-IF-NANO])
+
+dnl requires AC_INIT to be called before
+dnl For projects using a fourth or nano number in your versioning to indicate
+dnl development or prerelease snapshots, this macro allows the build to be
+dnl set up differently accordingly.
+
+dnl this macro:
+dnl - parses AC_PACKAGE_VERSION, set by AC_INIT, and extracts the nano number
+dnl - sets the variable PACKAGE_VERSION_NANO
+dnl - sets the variable PACKAGE_VERSION_RELEASE, which can be used
+dnl for rpm release fields
+dnl - executes ACTION-IF-NO-NANO or ACTION-IF-NANO
+
+dnl example:
+dnl AS_NANO(RELEASE="yes", RELEASE="no")
+
+AC_DEFUN([AS_NANO],
+[
+ AC_MSG_CHECKING(nano version)
+
+ NANO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f4)
+
+ if test x"$NANO" = x || test "x$NANO" = "x0" ; then
+ AC_MSG_RESULT([0 (release)])
+ NANO=0
+ PACKAGE_VERSION_RELEASE=1
+ ifelse([$1], , :, [$1])
+ else
+ AC_MSG_RESULT($NANO)
+ PACKAGE_VERSION_RELEASE=0.`date +%Y%m%d.%H%M%S`
+ ifelse([$2], , :, [$2])
+ fi
+ PACKAGE_VERSION_NANO=$NANO
+ AC_SUBST(PACKAGE_VERSION_NANO)
+ AC_SUBST(PACKAGE_VERSION_RELEASE)
+])
diff --git a/tools/missing-macros/src/m4/dnet.m4 b/tools/missing-macros/src/m4/dnet.m4
new file mode 100644
index 0000000..b57ead2
--- /dev/null
+++ b/tools/missing-macros/src/m4/dnet.m4
@@ -0,0 +1,322 @@
+# dnet.m4 serial 1 (libdnet-1.11)
+
+dnl
+dnl Check for 4.4 BSD sa_len member in sockaddr struct
+dnl
+dnl usage: AC_DNET_SOCKADDR_SA_LEN
+dnl results: HAVE_SOCKADDR_SA_LEN (defined)
+dnl
+AC_DEFUN([AC_DNET_SOCKADDR_SA_LEN],
+ [AC_MSG_CHECKING(for sa_len in sockaddr struct)
+ AC_CACHE_VAL(ac_cv_dnet_sockaddr_has_sa_len,
+ AC_TRY_COMPILE([
+# ifndef _SOCKADDR_LEN
+# define _SOCKADDR_LEN 1
+# endif
+# include <sys/types.h>
+# include <sys/socket.h>],
+ [u_int i = sizeof(((struct sockaddr *)0)->sa_len)],
+ ac_cv_dnet_sockaddr_has_sa_len=yes,
+ ac_cv_dnet_sockaddr_has_sa_len=no))
+ AC_MSG_RESULT($ac_cv_dnet_sockaddr_has_sa_len)
+ if test $ac_cv_dnet_sockaddr_has_sa_len = yes ; then
+ AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1,
+ [Define if sockaddr struct has sa_len.])
+ fi])
+
+dnl
+dnl Check for sockaddr_in6 struct in <netinet/in.h>
+dnl
+dnl usage: AC_DNET_SOCKADDR_IN6
+dnl results: HAVE_SOCKADDR_IN6
+dnl
+AC_DEFUN([AC_DNET_SOCKADDR_IN6],
+ [AC_MSG_CHECKING(for sockaddr_in6 struct in <netinet/in.h>)
+ AC_CACHE_VAL(ac_cv_dnet_netinet_in_h_has_sockaddr_in6,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>],
+ [struct sockaddr_in6 sin6; sin6.sin6_family = AF_INET6;],
+ ac_cv_dnet_netinet_in_h_has_sockaddr_in6=yes,
+ ac_cv_dnet_netinet_in_h_has_sockaddr_in6=no))
+ AC_MSG_RESULT($ac_cv_dnet_netinet_in_h_has_sockaddr_in6)
+ if test $ac_cv_dnet_netinet_in_h_has_sockaddr_in6 = yes ; then
+ AC_DEFINE(HAVE_SOCKADDR_IN6, 1,
+ [Define if <netinet/in.h> has sockaddr_in6 struct.])
+ fi])
+
+dnl
+dnl Check for arp_dev member in arpreq struct
+dnl
+dnl usage: AC_DNET_ARPREQ_ARP_DEV
+dnl results: HAVE_ARPREQ_ARP_DEV (defined)
+dnl
+AC_DEFUN([AC_DNET_ARPREQ_ARP_DEV],
+ [AC_MSG_CHECKING(for arp_dev in arpreq struct)
+ AC_CACHE_VAL(ac_cv_dnet_arpreq_has_arp_dev,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <net/if_arp.h>],
+ [void *p = ((struct arpreq *)0)->arp_dev],
+ ac_cv_dnet_arpreq_has_arp_dev=yes,
+ ac_cv_dnet_arpreq_has_arp_dev=no))
+ AC_MSG_RESULT($ac_cv_dnet_arpreq_has_arp_dev)
+ if test $ac_cv_dnet_arpreq_has_arp_dev = yes ; then
+ AC_DEFINE(HAVE_ARPREQ_ARP_DEV, 1,
+ [Define if arpreq struct has arp_dev.])
+ fi])
+
+dnl
+dnl Check for rt_msghdr struct in <net/route.h>
+dnl
+dnl usage: AC_DNET_ROUTE_RT_MSGHDR
+dnl results: HAVE_ROUTE_RT_MSGHDR
+dnl
+AC_DEFUN([AC_DNET_ROUTE_RT_MSGHDR],
+ [AC_MSG_CHECKING(for rt_msghdr struct in <net/route.h>)
+ AC_CACHE_VAL(ac_cv_dnet_route_h_has_rt_msghdr,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <net/if.h>
+# include <net/route.h>],
+ [struct rt_msghdr rtm; rtm.rtm_msglen = 0;],
+ ac_cv_dnet_route_h_has_rt_msghdr=yes,
+ ac_cv_dnet_route_h_has_rt_msghdr=no))
+ AC_MSG_RESULT($ac_cv_dnet_route_h_has_rt_msghdr)
+ if test $ac_cv_dnet_route_h_has_rt_msghdr = yes ; then
+ AC_DEFINE(HAVE_ROUTE_RT_MSGHDR, 1,
+ [Define if <net/route.h> has rt_msghdr struct.])
+ fi])
+
+dnl
+dnl Check for the Berkeley Packet Filter
+dnl
+dnl usage: AC_DNET_BSD_BPF
+dnl results: HAVE_BSD_BPF
+dnl
+AC_DEFUN([AC_DNET_BSD_BPF],
+ [AC_MSG_CHECKING(for Berkeley Packet Filter)
+ AC_CACHE_VAL(ac_cv_dnet_bsd_bpf,
+ if test -c /dev/bpf0 ; then
+ ac_cv_dnet_bsd_bpf=yes
+ else
+ ac_cv_dnet_bsd_bpf=no
+ fi)
+ AC_MSG_RESULT($ac_cv_dnet_bsd_bpf)
+ if test $ac_cv_dnet_bsd_bpf = yes ; then
+ AC_DEFINE(HAVE_BSD_BPF, 1,
+ [Define if you have the Berkeley Packet Filter.])
+ fi])
+
+dnl
+dnl Check for the Linux /proc filesystem
+dnl
+dnl usage: AC_DNET_LINUX_PROCFS
+dnl results: HAVE_LINUX_PROCFS
+dnl
+AC_DEFUN([AC_DNET_LINUX_PROCFS],
+ [AC_MSG_CHECKING(for Linux proc filesystem)
+ AC_CACHE_VAL(ac_cv_dnet_linux_procfs,
+ if test "x`cat /proc/sys/kernel/ostype 2>&-`" = "xLinux" ; then
+ ac_cv_dnet_linux_procfs=yes
+ else
+ ac_cv_dnet_linux_procfs=no
+ fi)
+ AC_MSG_RESULT($ac_cv_dnet_linux_procfs)
+ if test $ac_cv_dnet_linux_procfs = yes ; then
+ AC_DEFINE(HAVE_LINUX_PROCFS, 1,
+ [Define if you have the Linux /proc filesystem.])
+ fi])
+
+dnl
+dnl Check for Linux PF_PACKET sockets
+dnl
+dnl usage: AC_DNET_LINUX_PF_PACKET
+dnl results: HAVE_LINUX_PF_PACKET
+dnl
+AC_DEFUN([AC_DNET_LINUX_PF_PACKET],
+ [AC_MSG_CHECKING(for Linux PF_PACKET sockets)
+ AC_CACHE_VAL(ac_cv_dnet_linux_pf_packet,
+ if test -f /usr/include/netpacket/packet.h ; then
+ ac_cv_dnet_linux_pf_packet=yes
+ else
+ ac_cv_dnet_linux_pf_packet=no
+ fi)
+ AC_MSG_RESULT($ac_cv_dnet_linux_pf_packet)
+ if test $ac_cv_dnet_linux_pf_packet = yes ; then
+ AC_DEFINE(HAVE_LINUX_PF_PACKET, 1,
+ [Define if you have Linux PF_PACKET sockets.])
+ fi])
+
+dnl
+dnl Check for SNMP MIB2 STREAMS (Solaris only?)
+dnl
+dnl usage: AC_DNET_STREAMS_MIB2
+dnl results: HAVE_STREAMS_MIB2
+dnl
+AC_DEFUN([AC_DNET_STREAMS_MIB2],
+ [AC_MSG_CHECKING(for SNMP MIB2 STREAMS)
+ AC_CACHE_VAL(ac_cv_dnet_streams_mib2,
+ if test -f /usr/include/inet/mib2.h -a -c /dev/ip ; then
+ ac_cv_dnet_streams_mib2=yes
+ else
+ ac_cv_dnet_streams_mib2=no
+ fi)
+ AC_MSG_RESULT($ac_cv_dnet_streams_mib2)
+ if test $ac_cv_dnet_streams_mib2 = yes ; then
+ AC_DEFINE(HAVE_STREAMS_MIB2, 1,
+ [Define if you have SNMP MIB2 STREAMS.])
+ fi])
+
+dnl
+dnl Check for route(7) STREAMS (UnixWare only?)
+dnl
+dnl usage: AC_DNET_STREAMS_ROUTE
+dnl results: HAVE_STREAMS_ROUTE
+dnl
+AC_DEFUN([AC_DNET_STREAMS_ROUTE],
+ [AC_MSG_CHECKING(for route(7) STREAMS)
+ AC_CACHE_VAL(ac_cv_dnet_streams_route,
+ if grep RTSTR_SEND /usr/include/net/route.h >/dev/null 2>&1 ; then
+ ac_cv_dnet_streams_route=yes
+ else
+ ac_cv_dnet_streams_route=no
+ fi)
+ AC_MSG_RESULT($ac_cv_dnet_streams_route)
+ if test $ac_cv_dnet_streams_route = yes ; then
+ AC_DEFINE(HAVE_STREAMS_ROUTE, 1,
+ [Define if you have route(7) STREAMS.])
+ fi])
+
+dnl
+dnl Check for arp(7) ioctls
+dnl
+dnl usage: AC_DNET_IOCTL_ARP
+dnl results: HAVE_IOCTL_ARP
+dnl
+AC_DEFUN([AC_DNET_IOCTL_ARP],
+ [AC_MSG_CHECKING(for arp(7) ioctls)
+ AC_CACHE_VAL(ac_cv_dnet_ioctl_arp,
+ AC_EGREP_CPP(werd, [
+# include <sys/types.h>
+# define BSD_COMP
+# include <sys/ioctl.h>
+# ifdef SIOCGARP
+ werd
+# endif],
+ ac_cv_dnet_ioctl_arp=yes,
+ ac_cv_dnet_ioctl_arp=no))
+ case "$host_os" in
+ irix*)
+ ac_cv_dnet_ioctl_arp=no ;;
+ esac
+ AC_MSG_RESULT($ac_cv_dnet_ioctl_arp)
+ if test $ac_cv_dnet_ioctl_arp = yes ; then
+ AC_DEFINE(HAVE_IOCTL_ARP, 1,
+ [Define if you have arp(7) ioctls.])
+ fi])
+
+dnl
+dnl Check for raw IP sockets ip_{len,off} host byte ordering
+dnl
+dnl usage: AC_DNET_RAWIP_HOST_OFFLEN
+dnl results: HAVE_RAWIP_HOST_OFFLEN
+dnl
+AC_DEFUN([AC_DNET_RAWIP_HOST_OFFLEN],
+ [AC_MSG_CHECKING([for raw IP sockets ip_{len,off} host byte ordering])
+ AC_CACHE_VAL(ac_cv_dnet_rawip_host_offlen, [
+ case "$host_os" in
+ *openbsd*)
+ ac_cv_dnet_rawip_host_offlen=no ;;
+ *bsd*|*osf*|*unixware*)
+ ac_cv_dnet_rawip_host_offlen=yes ;;
+ *)
+ ac_cv_dnet_rawip_host_offlen=no ;;
+ esac])
+ AC_MSG_RESULT($ac_cv_dnet_rawip_host_offlen)
+ if test $ac_cv_dnet_rawip_host_offlen = yes ; then
+ AC_DEFINE(HAVE_RAWIP_HOST_OFFLEN, 1,
+ [Define if raw IP sockets require host byte ordering for ip_off, ip_len.])
+ fi])
+
+dnl
+dnl Check for cooked raw IP sockets
+dnl
+dnl usage: AC_DNET_RAWIP_COOKED
+dnl results: HAVE_RAWIP_COOKED
+dnl
+AC_DEFUN([AC_DNET_RAWIP_COOKED],
+ [AC_MSG_CHECKING(for cooked raw IP sockets)
+ AC_CACHE_VAL(ac_cv_dnet_rawip_cooked, [
+ case "$host_os" in
+ solaris*|irix*)
+ ac_cv_dnet_rawip_cooked=yes ;;
+ *)
+ ac_cv_dnet_rawip_cooked=no ;;
+ esac])
+ AC_MSG_RESULT($ac_cv_dnet_rawip_cooked)
+ if test $ac_cv_dnet_rawip_cooked = yes ; then
+ AC_DEFINE(HAVE_RAWIP_COOKED, 1,
+ [Define if you have cooked raw IP sockets.])
+ fi])
+
+dnl
+dnl AC_LBL_LIBRARY_NET
+dnl
+dnl This test is for network applications that need socket() and
+dnl gethostbyname() -ish functions. Under Solaris, those applications
+dnl need to link with "-lsocket -lnsl". Under IRIX, they need to link
+dnl with "-lnsl" but should *not* link with "-lsocket" because
+dnl libsocket.a breaks a number of things (for instance:
+dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
+dnl versions of IRIX).
+dnl
+dnl Unfortunately, many application developers are not aware of this,
+dnl and mistakenly write tests that cause -lsocket to be used under
+dnl IRIX. It is also easy to write tests that cause -lnsl to be used
+dnl under operating systems where neither are necessary (or useful),
+dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
+dnl
+dnl This test exists so that every application developer does not test
+dnl this in a different, and subtly broken fashion.
+
+dnl It has been argued that this test should be broken up into two
+dnl seperate tests, one for the resolver libraries, and one for the
+dnl libraries necessary for using Sockets API. Unfortunately, the two
+dnl are carefully intertwined and allowing the autoconf user to use
+dnl them independantly potentially results in unfortunate ordering
+dnl dependancies -- as such, such component macros would have to
+dnl carefully use indirection and be aware if the other components were
+dnl executed. Since other autoconf macros do not go to this trouble,
+dnl and almost no applications use sockets without the resolver, this
+dnl complexity has not been implemented.
+dnl
+dnl The check for libresolv is in case you are attempting to link
+dnl statically and happen to have a libresolv.a lying around (and no
+dnl libnsl.a).
+dnl
+AC_DEFUN([AC_LBL_LIBRARY_NET], [
+ # Most operating systems have gethostbyname() in the default searched
+ # libraries (i.e. libc):
+ AC_CHECK_FUNC(gethostbyname, ,
+ # Some OSes (eg. Solaris) place it in libnsl:
+ AC_CHECK_LIB(nsl, gethostbyname, ,
+ # Some strange OSes (SINIX) have it in libsocket:
+ AC_CHECK_LIB(socket, gethostbyname, ,
+ # Unfortunately libsocket sometimes depends on libnsl.
+ # AC_CHECK_LIB's API is essentially broken so the
+ # following ugliness is necessary:
+ AC_CHECK_LIB(socket, gethostbyname,
+ LIBS="-lsocket -lnsl $LIBS",
+ AC_CHECK_LIB(resolv, gethostbyname),
+ -lnsl))))
+ AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, ,
+ AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", ,
+ -lnsl)))
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ AC_CHECK_LIB(str, putmsg)
+ ])
+
diff --git a/tools/missing-macros/src/m4/fake-gtk-doc-check.m4 b/tools/missing-macros/src/m4/fake-gtk-doc-check.m4
new file mode 100644
index 0000000..26fa723
--- /dev/null
+++ b/tools/missing-macros/src/m4/fake-gtk-doc-check.m4
@@ -0,0 +1,13 @@
+dnl fake-gtk-doc-check.m4 serial 1 (OpenWrt)
+dnl Provide a fake GTK_DOC_CHECK macros which
+dnl always defines false.
+
+AC_DEFUN([GTK_DOC_CHECK],
+[
+ AM_CONDITIONAL([ENABLE_GTK_DOC], [false])
+ AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [false])
+ AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [false])
+ AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [false])
+ AM_CONDITIONAL([GTK_DOC_USE_REBASE], [false])
+ AC_PATH_PROGS([GTKDOC_REBASE],[true],[true])
+])
diff --git a/tools/missing-macros/src/m4/fake-intltool.m4 b/tools/missing-macros/src/m4/fake-intltool.m4
new file mode 100644
index 0000000..352053c
--- /dev/null
+++ b/tools/missing-macros/src/m4/fake-intltool.m4
@@ -0,0 +1,16 @@
+# stripped intltool.m4 to make automake happy
+# serial 1
+AC_DEFUN([IT_PROG_INTLTOOL],
+[
+ AC_SUBST(ALL_LINGUAS)
+
+ DATADIRNAME=share
+ AC_SUBST(DATADIRNAME)
+])
+
+# deprecated macros
+AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
+
+# A hint is needed for aclocal from Automake <= 1.9.4:
+# AC_DEFUN([AC_PROG_INTLTOOL], ...)
+
diff --git a/tools/missing-macros/src/m4/glibc2.m4 b/tools/missing-macros/src/m4/glibc2.m4
new file mode 100644
index 0000000..f148c12
--- /dev/null
+++ b/tools/missing-macros/src/m4/glibc2.m4
@@ -0,0 +1,30 @@
+# glibc2.m4 serial 2
+dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Test for the GNU C Library, version 2.0 or newer.
+# From Bruno Haible.
+
+AC_DEFUN([gt_GLIBC2],
+ [
+ AC_CACHE_CHECK([whether we are using the GNU C Library 2 or newer],
+ [ac_cv_gnu_library_2],
+ [AC_EGREP_CPP([Lucky GNU user],
+ [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ >= 2)
+ Lucky GNU user
+ #endif
+#endif
+ ],
+ [ac_cv_gnu_library_2=yes],
+ [ac_cv_gnu_library_2=no])
+ ]
+ )
+ AC_SUBST([GLIBC2])
+ GLIBC2="$ac_cv_gnu_library_2"
+ ]
+)
diff --git a/tools/missing-macros/src/m4/glibc21.m4 b/tools/missing-macros/src/m4/glibc21.m4
new file mode 100644
index 0000000..68ada9d
--- /dev/null
+++ b/tools/missing-macros/src/m4/glibc21.m4
@@ -0,0 +1,30 @@
+# glibc21.m4 serial 4
+dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Test for the GNU C Library, version 2.1 or newer.
+# From Bruno Haible.
+
+AC_DEFUN([gl_GLIBC21],
+ [
+ AC_CACHE_CHECK([whether we are using the GNU C Library 2.1 or newer],
+ [ac_cv_gnu_library_2_1],
+ [AC_EGREP_CPP([Lucky GNU user],
+ [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+ Lucky GNU user
+ #endif
+#endif
+ ],
+ [ac_cv_gnu_library_2_1=yes],
+ [ac_cv_gnu_library_2_1=no])
+ ]
+ )
+ AC_SUBST([GLIBC21])
+ GLIBC21="$ac_cv_gnu_library_2_1"
+ ]
+)
diff --git a/tools/missing-macros/src/m4/intdiv0.m4 b/tools/missing-macros/src/m4/intdiv0.m4
new file mode 100644
index 0000000..289c4df
--- /dev/null
+++ b/tools/missing-macros/src/m4/intdiv0.m4
@@ -0,0 +1,84 @@
+# intdiv0.m4 serial 3 (gettext-0.18)
+dnl Copyright (C) 2002, 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gt_INTDIV0],
+[
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+ AC_CACHE_CHECK([whether integer division by zero raises SIGFPE],
+ gt_cv_int_divbyzero_sigfpe,
+ [
+ gt_cv_int_divbyzero_sigfpe=
+changequote(,)dnl
+ case "$host_os" in
+ macos* | darwin[6-9]* | darwin[1-9][0-9]*)
+ # On MacOS X 10.2 or newer, just assume the same as when cross-
+ # compiling. If we were to perform the real test, 1 Crash Report
+ # dialog window would pop up.
+ case "$host_cpu" in
+ i[34567]86 | x86_64)
+ gt_cv_int_divbyzero_sigfpe="guessing yes" ;;
+ esac
+ ;;
+ esac
+changequote([,])dnl
+ if test -z "$gt_cv_int_divbyzero_sigfpe"; then
+ AC_TRY_RUN([
+#include <stdlib.h>
+#include <signal.h>
+
+static void
+sigfpe_handler (int sig)
+{
+ /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */
+ exit (sig != SIGFPE);
+}
+
+int x = 1;
+int y = 0;
+int z;
+int nan;
+
+int main ()
+{
+ signal (SIGFPE, sigfpe_handler);
+/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */
+#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP)
+ signal (SIGTRAP, sigfpe_handler);
+#endif
+/* Linux/SPARC yields signal SIGILL. */
+#if defined (__sparc__) && defined (__linux__)
+ signal (SIGILL, sigfpe_handler);
+#endif
+
+ z = x / y;
+ nan = y / y;
+ exit (1);
+}
+], [gt_cv_int_divbyzero_sigfpe=yes], [gt_cv_int_divbyzero_sigfpe=no],
+ [
+ # Guess based on the CPU.
+changequote(,)dnl
+ case "$host_cpu" in
+ alpha* | i[34567]86 | x86_64 | m68k | s390*)
+ gt_cv_int_divbyzero_sigfpe="guessing yes";;
+ *)
+ gt_cv_int_divbyzero_sigfpe="guessing no";;
+ esac
+changequote([,])dnl
+ ])
+ fi
+ ])
+ case "$gt_cv_int_divbyzero_sigfpe" in
+ *yes) value=1;;
+ *) value=0;;
+ esac
+ AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value],
+ [Define if integer division by zero raises signal SIGFPE.])
+])
diff --git a/tools/missing-macros/src/m4/intmax.m4 b/tools/missing-macros/src/m4/intmax.m4
new file mode 100644
index 0000000..74aaaf5
--- /dev/null
+++ b/tools/missing-macros/src/m4/intmax.m4
@@ -0,0 +1,33 @@
+# intmax.m4 serial 5 (gettext-0.18)
+dnl Copyright (C) 2002-2005, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether the system has the 'intmax_t' type, but don't attempt to
+dnl find a replacement if it is lacking.
+
+AC_DEFUN([gt_TYPE_INTMAX_T],
+[
+ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+ AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t],
+ [AC_TRY_COMPILE([
+#include <stddef.h>
+#include <stdlib.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+#include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+#include <inttypes.h>
+#endif
+], [intmax_t x = -1;
+ return !x;],
+ [gt_cv_c_intmax_t=yes],
+ [gt_cv_c_intmax_t=no])])
+ if test $gt_cv_c_intmax_t = yes; then
+ AC_DEFINE([HAVE_INTMAX_T], [1],
+ [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
+ fi
+])
diff --git a/tools/missing-macros/src/m4/inttypes-pri.m4 b/tools/missing-macros/src/m4/inttypes-pri.m4
new file mode 100644
index 0000000..718a4f4
--- /dev/null
+++ b/tools/missing-macros/src/m4/inttypes-pri.m4
@@ -0,0 +1,36 @@
+# inttypes-pri.m4 serial 6 (gettext-0.18)
+dnl Copyright (C) 1997-2002, 2006, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ([2.52])
+
+# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI*
+# macros to non-string values. This is the case on AIX 4.3.3.
+
+AC_DEFUN([gt_INTTYPES_PRI],
+[
+ AC_CHECK_HEADERS([inttypes.h])
+ if test $ac_cv_header_inttypes_h = yes; then
+ AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken],
+ [gt_cv_inttypes_pri_broken],
+ [
+ AC_TRY_COMPILE([#include <inttypes.h>
+#ifdef PRId32
+char *p = PRId32;
+#endif
+], [], [gt_cv_inttypes_pri_broken=no], [gt_cv_inttypes_pri_broken=yes])
+ ])
+ fi
+ if test "$gt_cv_inttypes_pri_broken" = yes; then
+ AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1],
+ [Define if <inttypes.h> exists and defines unusable PRI* macros.])
+ PRI_MACROS_BROKEN=1
+ else
+ PRI_MACROS_BROKEN=0
+ fi
+ AC_SUBST([PRI_MACROS_BROKEN])
+])
diff --git a/tools/missing-macros/src/m4/inttypes_h.m4 b/tools/missing-macros/src/m4/inttypes_h.m4
new file mode 100644
index 0000000..782d77e
--- /dev/null
+++ b/tools/missing-macros/src/m4/inttypes_h.m4
@@ -0,0 +1,26 @@
+# inttypes_h.m4 serial 9
+dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_INTTYPES_H],
+[
+ AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h],
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [uintmax_t i = (uintmax_t) -1; return !i;],
+ [gl_cv_header_inttypes_h=yes],
+ [gl_cv_header_inttypes_h=no])])
+ if test $gl_cv_header_inttypes_h = yes; then
+ AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1],
+ [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
diff --git a/tools/missing-macros/src/m4/lib-ld.m4 b/tools/missing-macros/src/m4/lib-ld.m4
new file mode 100644
index 0000000..ebb3052
--- /dev/null
+++ b/tools/missing-macros/src/m4/lib-ld.m4
@@ -0,0 +1,110 @@
+# lib-ld.m4 serial 4 (gettext-0.18)
+dnl Copyright (C) 1996-2003, 2009-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld],
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ acl_cv_prog_gnu_ld=yes ;;
+*)
+ acl_cv_prog_gnu_ld=no ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]* | [A-Za-z]:[\\/]*)]
+ [re_direlt='/[^/][^/]*/\.\./']
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL([acl_cv_path_LD],
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break ;;
+ *)
+ test "$with_gnu_ld" != yes && break ;;
+ esac
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT([$LD])
+else
+ AC_MSG_RESULT([no])
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
diff --git a/tools/missing-macros/src/m4/lib-link.m4 b/tools/missing-macros/src/m4/lib-link.m4
new file mode 100644
index 0000000..c73bd8e
--- /dev/null
+++ b/tools/missing-macros/src/m4/lib-link.m4
@@ -0,0 +1,774 @@
+# lib-link.m4 serial 21 (gettext-0.18)
+dnl Copyright (C) 2001-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ([2.54])
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ pushdef([Name],[translit([$1],[./-], [___])])
+ pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+ ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+ ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+ ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+ ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+ ])
+ LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+ LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+ INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+ LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+ dnl results of this search when this library appears as a dependency.
+ HAVE_LIB[]NAME=yes
+ popdef([NAME])
+ popdef([Name])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message])
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. The missing-message
+dnl defaults to 'no' and may contain additional hints for the user.
+dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME}
+dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ pushdef([Name],[translit([$1],[./-], [___])])
+ pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+ dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+ dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed lib[]Name and not disabled its use
+ dnl via --without-lib[]Name-prefix, he wants to use it.
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+ AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+ ac_save_LIBS="$LIBS"
+ dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS,
+ dnl because these -l options might require -L options that are present in
+ dnl LIBS. -l options benefit only from the -L options listed before it.
+ dnl Otherwise, add it to the front of LIBS, because it may be a static
+ dnl library that depends on another static library that is present in LIBS.
+ dnl Static libraries benefit only from the static libraries listed after
+ dnl it.
+ case " $LIB[]NAME" in
+ *" -l"*) LIBS="$LIBS $LIB[]NAME" ;;
+ *) LIBS="$LIB[]NAME $LIBS" ;;
+ esac
+ AC_TRY_LINK([$3], [$4],
+ [ac_cv_lib[]Name=yes],
+ [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])'])
+ LIBS="$ac_save_LIBS"
+ ])
+ if test "$ac_cv_lib[]Name" = yes; then
+ HAVE_LIB[]NAME=yes
+ AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.])
+ AC_MSG_CHECKING([how to link with lib[]$1])
+ AC_MSG_RESULT([$LIB[]NAME])
+ else
+ HAVE_LIB[]NAME=no
+ dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+ dnl $INC[]NAME either.
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIB[]NAME=
+ LTLIB[]NAME=
+ LIB[]NAME[]_PREFIX=
+ fi
+ AC_SUBST([HAVE_LIB]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ popdef([NAME])
+ popdef([Name])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl acl_libext,
+dnl acl_shlibext,
+dnl acl_hardcode_libdir_flag_spec,
+dnl acl_hardcode_libdir_separator,
+dnl acl_hardcode_direct,
+dnl acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+ dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+ m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
+ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
+ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+ AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+ ])
+ wl="$acl_cv_wl"
+ acl_libext="$acl_cv_libext"
+ acl_shlibext="$acl_cv_shlibext"
+ acl_libname_spec="$acl_cv_libname_spec"
+ acl_library_names_spec="$acl_cv_library_names_spec"
+ acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ acl_hardcode_direct="$acl_cv_hardcode_direct"
+ acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ dnl Determine whether the user wants rpath handling at all.
+ AC_ARG_ENABLE([rpath],
+ [ --disable-rpath do not hardcode runtime library paths],
+ :, enable_rpath=yes)
+])
+
+dnl AC_LIB_FROMPACKAGE(name, package)
+dnl declares that libname comes from the given package. The configure file
+dnl will then not have a --with-libname-prefix option but a
+dnl --with-package-prefix option. Several libraries can come from the same
+dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
+dnl macro call that searches for libname.
+AC_DEFUN([AC_LIB_FROMPACKAGE],
+[
+ pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ define([acl_frompackage_]NAME, [$2])
+ popdef([NAME])
+ pushdef([PACK],[$2])
+ pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ define([acl_libsinpackage_]PACKUP,
+ m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1])
+ popdef([PACKUP])
+ popdef([PACK])
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
+ pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
+ dnl Autoconf >= 2.61 supports dots in --with options.
+ pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_ARG_WITH(P_A_C_K[-prefix],
+[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib
+ --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ if test "$acl_libdirstem2" != "$acl_libdirstem" \
+ && ! test -d "$withval/$acl_libdirstem"; then
+ additional_libdir="$withval/$acl_libdirstem2"
+ fi
+ fi
+ fi
+])
+ dnl Search the library and its dependencies in $additional_libdir and
+ dnl $LDFLAGS. Using breadth-first-seach.
+ LIB[]NAME=
+ LTLIB[]NAME=
+ INC[]NAME=
+ LIB[]NAME[]_PREFIX=
+ dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
+ dnl computed. So it has to be reset here.
+ HAVE_LIB[]NAME=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='$1 $2'
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+ dnl or AC_LIB_HAVE_LINKFLAGS call.
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+ else
+ dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+ dnl that this library doesn't exist. So just drop it.
+ :
+ fi
+ else
+ dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+ dnl and the already constructed $LIBNAME/$LTLIBNAME.
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
+ if test -n "$acl_shlibext"; then
+ shrext=".$acl_shlibext" # typically: shrext=.so
+ else
+ shrext=
+ fi
+ if test $use_additional = yes; then
+ dir="$additional_libdir"
+ dnl The same code as in the loop below:
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ dnl Found the library.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ dnl Linking with a shared library. We attempt to hardcode its
+ dnl directory into the executable's runpath, unless it's the
+ dnl standard /usr/lib.
+ if test "$enable_rpath" = no \
+ || test "X$found_dir" = "X/usr/$acl_libdirstem" \
+ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then
+ dnl No hardcoding is needed.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ dnl The hardcoding into $LIBNAME is system dependent.
+ if test "$acl_hardcode_direct" = yes; then
+ dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+ dnl resulting binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ dnl Rely on "-L$found_dir".
+ dnl But don't add it if it's already contained in the LDFLAGS
+ dnl or the already constructed $LIBNAME
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+ fi
+ if test "$acl_hardcode_minus_L" != no; then
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+ dnl here, because this doesn't fit in flags passed to the
+ dnl compiler. So give up. No hardcoding. This affects only
+ dnl very old systems.
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ dnl Linking with a static library.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+ else
+ dnl We shouldn't come here, but anyway it's good to have a
+ dnl fallback.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+ fi
+ fi
+ dnl Assume the include files are nearby.
+ additional_includedir=
+ case "$found_dir" in
+ */$acl_libdirstem | */$acl_libdirstem/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+ if test "$name" = '$1'; then
+ LIB[]NAME[]_PREFIX="$basedir"
+ fi
+ additional_includedir="$basedir/include"
+ ;;
+ */$acl_libdirstem2 | */$acl_libdirstem2/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
+ if test "$name" = '$1'; then
+ LIB[]NAME[]_PREFIX="$basedir"
+ fi
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ dnl Potentially add $additional_includedir to $INCNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 3. if it's already present in $CPPFLAGS or the already
+ dnl constructed $INCNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INC[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $INCNAME.
+ INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ dnl Look for dependencies.
+ if test -n "$found_la"; then
+ dnl Read the .la file. It defines the variables
+ dnl dlname, library_names, old_library, dependency_libs, current,
+ dnl age, revision, installed, dlopen, dlpreopen, libdir.
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ dnl We use only dependency_libs.
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 3. if it's already present in $LDFLAGS or the already
+ dnl constructed $LIBNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \
+ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
+ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LIBNAME.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LTLIBNAME.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ dnl Handle this in the next round.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ dnl Handle this in the next round. Throw away the .la's
+ dnl directory; it is already contained in a preceding -L
+ dnl option.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ dnl Most likely an immediate library name.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ dnl Didn't find the library; assume it is in the system directories
+ dnl known to the linker and runtime loader. (All the system
+ dnl directories known to the linker should also be known to the
+ dnl runtime loader, otherwise the system is severely misconfigured.)
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user must
+ dnl pass all path elements in one option. We can arrange that for a
+ dnl single library, but not when more than one $LIBNAMEs are used.
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+ done
+ dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ dnl When using libtool, the option that works for both libraries and
+ dnl executables is -R. The -R options are cumulative.
+ for found_dir in $ltrpathdirs; do
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+ done
+ fi
+ popdef([P_A_C_K])
+ popdef([PACKLIBS])
+ popdef([PACKUP])
+ popdef([PACK])
+ popdef([NAME])
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+ for element in [$2]; do
+ haveit=
+ for x in $[$1]; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ [$1]="${[$1]}${[$1]:+ }$element"
+ fi
+ done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+ AC_REQUIRE([AC_LIB_RPATH])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ $1=
+ if test "$enable_rpath" != no; then
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode directories into the resulting
+ dnl binary.
+ rpathdirs=
+ next=
+ for opt in $2; do
+ if test -n "$next"; then
+ dir="$next"
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem" \
+ && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next=
+ else
+ case $opt in
+ -L) next=yes ;;
+ -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem" \
+ && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next= ;;
+ *) next= ;;
+ esac
+ fi
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n ""$3""; then
+ dnl libtool is used for linking. Use -R options.
+ for dir in $rpathdirs; do
+ $1="${$1}${$1:+ }-R$dir"
+ done
+ else
+ dnl The linker is used for linking directly.
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user
+ dnl must pass all path elements in one option.
+ alldirs=
+ for dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="${$1}${$1:+ }$flag"
+ done
+ fi
+ fi
+ fi
+ fi
+ fi
+ AC_SUBST([$1])
+])
diff --git a/tools/missing-macros/src/m4/lib-prefix.m4 b/tools/missing-macros/src/m4/lib-prefix.m4
new file mode 100644
index 0000000..1601cea
--- /dev/null
+++ b/tools/missing-macros/src/m4/lib-prefix.m4
@@ -0,0 +1,224 @@
+# lib-prefix.m4 serial 7 (gettext-0.18)
+dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+ AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib-prefix],
+[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+ --without-lib-prefix don't search for libraries in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+])
+ if test $use_additional = yes; then
+ dnl Potentially add $additional_includedir to $CPPFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's already present in $CPPFLAGS,
+ dnl 3. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ for x in $CPPFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $CPPFLAGS.
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ dnl Potentially add $additional_libdir to $LDFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's already present in $LDFLAGS,
+ dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ for x in $LDFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LDFLAGS.
+ LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+ dnl Unfortunately, prefix and exec_prefix get only finally determined
+ dnl at the end of configure.
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ $1
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates
+dnl - a variable acl_libdirstem, containing the basename of the libdir, either
+dnl "lib" or "lib64" or "lib/64",
+dnl - a variable acl_libdirstem2, as a secondary possible value for
+dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
+dnl "lib/amd64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+ dnl There is no formal standard regarding lib and lib64.
+ dnl On glibc systems, the current practice is that on a system supporting
+ dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+ dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
+ dnl the compiler's default mode by looking at the compiler's library search
+ dnl path. If at least one of its elements ends in /lib64 or points to a
+ dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
+ dnl Otherwise we use the default, namely "lib".
+ dnl On Solaris systems, the current practice is that on a system supporting
+ dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+ dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
+ dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ acl_libdirstem=lib
+ acl_libdirstem2=
+ case "$host_os" in
+ solaris*)
+ dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment
+ dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>.
+ dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
+ dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
+ dnl symlink is missing, so we set acl_libdirstem2 too.
+ AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
+ [AC_EGREP_CPP([sixtyfour bits], [
+#ifdef _LP64
+sixtyfour bits
+#endif
+ ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
+ ])
+ if test $gl_cv_solaris_64bit = yes; then
+ acl_libdirstem=lib/64
+ case "$host_cpu" in
+ sparc*) acl_libdirstem2=lib/sparcv9 ;;
+ i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
+ esac
+ fi
+ ;;
+ *)
+ searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ */../ | */.. )
+ # Better ignore directories of this form. They are misleading.
+ ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+ ;;
+ esac
+ test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
+])
diff --git a/tools/missing-macros/src/m4/mfx_acc.m4 b/tools/missing-macros/src/m4/mfx_acc.m4
new file mode 100644
index 0000000..9685cc3
--- /dev/null
+++ b/tools/missing-macros/src/m4/mfx_acc.m4
@@ -0,0 +1,163 @@
+# acc.m4 serial 1 (ucl-1.03)
+# /***********************************************************************
+# // standard ACC macros
+# ************************************************************************/
+
+AC_DEFUN([mfx_ACC_CHECK_ENDIAN], [
+AC_C_BIGENDIAN([AC_DEFINE(ACC_ABI_BIG_ENDIAN,1,[Define to 1 if your machine is big endian.])],[AC_DEFINE(ACC_ABI_LITTLE_ENDIAN,1,[Define to 1 if your machine is little endian.])])
+])#
+
+AC_DEFUN([mfx_ACC_CHECK_HEADERS], [
+AC_HEADER_TIME
+AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h limits.h malloc.h memory.h setjmp.h signal.h stdarg.h stddef.h stdint.h stdio.h stdlib.h string.h strings.h time.h unistd.h utime.h sys/mman.h sys/resource.h sys/stat.h sys/time.h sys/types.h sys/wait.h])
+])#
+
+AC_DEFUN([mfx_ACC_CHECK_FUNCS], [
+AC_CHECK_FUNCS(access alloca atexit atoi atol chmod chown clock_getcpuclockid clock_getres clock_gettime ctime difftime fstat getenv getpagesize getrusage gettimeofday gmtime isatty localtime longjmp lstat memcmp memcpy memmove memset mkdir mktime mmap mprotect munmap qsort raise rmdir setjmp signal snprintf strcasecmp strchr strdup strerror strftime stricmp strncasecmp strnicmp strrchr strstr time umask utime vsnprintf)
+])#
+
+
+AC_DEFUN([mfx_ACC_CHECK_SIZEOF], [
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+
+AC_CHECK_SIZEOF(long long)
+AC_CHECK_SIZEOF(__int16)
+AC_CHECK_SIZEOF(__int32)
+AC_CHECK_SIZEOF(__int64)
+
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(char *)
+AC_CHECK_SIZEOF(size_t)
+AC_CHECK_SIZEOF(ptrdiff_t)
+])#
+
+
+# /***********************************************************************
+# // Check for ACC_conformance
+# ************************************************************************/
+
+AC_DEFUN([mfx_ACC_ACCCHK], [
+mfx_tmp=$1
+mfx_save_CPPFLAGS=$CPPFLAGS
+dnl in Makefile.in $(INCLUDES) will be before $(CPPFLAGS), so we mimic this here
+test "X$mfx_tmp" = "X" || CPPFLAGS="$mfx_tmp $CPPFLAGS"
+
+AC_MSG_CHECKING([whether your compiler passes the ACC conformance test])
+
+AC_LANG_CONFTEST([AC_LANG_PROGRAM(
+[[#define ACC_CONFIG_NO_HEADER 1
+#include "acc/acc.h"
+#include "acc/acc_incd.h"
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT_HEADER(expr)
+#include "acc/acc_chk.ch"
+#undef ACCCHK_ASSERT
+static void test_acc_compile_time_assert(void) {
+#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
+#include "acc/acc_chk.ch"
+#undef ACCCHK_ASSERT
+}
+#undef NDEBUG
+#include <assert.h>
+static int test_acc_run_time_assert(int r) {
+#define ACCCHK_ASSERT(expr) assert(expr);
+#include "acc/acc_chk.ch"
+#undef ACCCHK_ASSERT
+return r;
+}
+]], [[
+test_acc_compile_time_assert();
+if (test_acc_run_time_assert(1) != 1) return 1;
+]]
+)])
+
+mfx_tmp=FAILED
+_AC_COMPILE_IFELSE([], [mfx_tmp=yes])
+rm -f conftest.$ac_ext conftest.$ac_objext
+
+CPPFLAGS=$mfx_save_CPPFLAGS
+
+AC_MSG_RESULT([$mfx_tmp])
+case x$mfx_tmp in
+ xpassed | xyes) ;;
+ *)
+ AC_MSG_NOTICE([])
+ AC_MSG_NOTICE([Your compiler failed the ACC conformance test - for details see ])
+ AC_MSG_NOTICE([`config.log'. Please check that log file and consider sending])
+ AC_MSG_NOTICE([a patch or bug-report to <${PACKAGE_BUGREPORT}>.])
+ AC_MSG_NOTICE([Thanks for your support.])
+ AC_MSG_NOTICE([])
+ AC_MSG_ERROR([ACC conformance test failed. Stop.])
+dnl AS_EXIT
+ ;;
+esac
+])# mfx_ACC_ACCCHK
+
+
+# /***********************************************************************
+# // Check for ACC_conformance
+# ************************************************************************/
+
+AC_DEFUN([mfx_MINIACC_ACCCHK], [
+mfx_tmp=$1
+mfx_save_CPPFLAGS=$CPPFLAGS
+dnl in Makefile.in $(INCLUDES) will be before $(CPPFLAGS), so we mimic this here
+test "X$mfx_tmp" = "X" || CPPFLAGS="$mfx_tmp $CPPFLAGS"
+
+AC_MSG_CHECKING([whether your compiler passes the ACC conformance test])
+
+AC_LANG_CONFTEST([AC_LANG_PROGRAM(
+[[#define ACC_CONFIG_NO_HEADER 1
+#define ACC_WANT_ACC_INCD_H 1
+#include $2
+
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT_HEADER(expr)
+#include $2
+
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
+static void test_acc_compile_time_assert(void) {
+#include $2
+}
+
+#undef NDEBUG
+#include <assert.h>
+#define ACC_WANT_ACC_CHK_CH 1
+#undef ACCCHK_ASSERT
+#define ACCCHK_ASSERT(expr) assert(expr);
+static int test_acc_run_time_assert(int r) {
+#include $2
+return r;
+}
+]], [[
+test_acc_compile_time_assert();
+if (test_acc_run_time_assert(1) != 1) return 1;
+]]
+)])
+
+mfx_tmp=FAILED
+_AC_COMPILE_IFELSE([], [mfx_tmp=yes])
+rm -f conftest.$ac_ext conftest.$ac_objext
+
+CPPFLAGS=$mfx_save_CPPFLAGS
+
+AC_MSG_RESULT([$mfx_tmp])
+case x$mfx_tmp in
+ xpassed | xyes) ;;
+ *)
+ AC_MSG_NOTICE([])
+ AC_MSG_NOTICE([Your compiler failed the ACC conformance test - for details see ])
+ AC_MSG_NOTICE([`config.log'. Please check that log file and consider sending])
+ AC_MSG_NOTICE([a patch or bug-report to <${PACKAGE_BUGREPORT}>.])
+ AC_MSG_NOTICE([Thanks for your support.])
+ AC_MSG_NOTICE([])
+ AC_MSG_ERROR([ACC conformance test failed. Stop.])
+dnl AS_EXIT
+ ;;
+esac
+])# mfx_MINIACC_ACCCHK
diff --git a/tools/missing-macros/src/m4/mfx_cppflags.m4 b/tools/missing-macros/src/m4/mfx_cppflags.m4
new file mode 100644
index 0000000..0ad9141
--- /dev/null
+++ b/tools/missing-macros/src/m4/mfx_cppflags.m4
@@ -0,0 +1,41 @@
+# serial 1
+
+AC_DEFUN([mfx_PROG_CPPFLAGS], [
+AC_MSG_CHECKING([whether the C preprocessor needs special flags])
+
+AC_LANG_CONFTEST([AC_LANG_PROGRAM(
+[[#include <limits.h>
+#if (32767 >= 4294967295ul) || (65535u >= 4294967295ul)
+# include "your C preprocessor is broken 1"
+#elif (0xffffu == 0xfffffffful)
+# include "your C preprocessor is broken 2"
+#elif (32767 >= ULONG_MAX) || (65535u >= ULONG_MAX)
+# include "your C preprocessor is broken 3"
+#endif
+]], [[ ]]
+)])
+
+mfx_save_CPPFLAGS=$CPPFLAGS
+mfx_tmp=ERROR
+for mfx_arg in "" -no-cpp-precomp
+do
+ CPPFLAGS="$mfx_arg $mfx_save_CPPFLAGS"
+ _AC_COMPILE_IFELSE([],
+[mfx_tmp=$mfx_arg
+break])
+done
+CPPFLAGS=$mfx_save_CPPFLAGS
+rm -f conftest.$ac_ext conftest.$ac_objext
+case x$mfx_tmp in
+ x)
+ AC_MSG_RESULT([none needed]) ;;
+ xERROR)
+ AC_MSG_RESULT([ERROR])
+ AC_MSG_ERROR([your C preprocessor is broken - for details see config.log])
+ ;;
+ *)
+ AC_MSG_RESULT([$mfx_tmp])
+ CPPFLAGS="$mfx_tmp $CPPFLAGS"
+ ;;
+esac
+])# mfx_PROG_CPPFLAGS
diff --git a/tools/missing-macros/src/m4/mfx_limits.m4 b/tools/missing-macros/src/m4/mfx_limits.m4
new file mode 100644
index 0000000..d63a14b
--- /dev/null
+++ b/tools/missing-macros/src/m4/mfx_limits.m4
@@ -0,0 +1,154 @@
+# serial 3
+
+AC_DEFUN([mfx_CHECK_HEADER_SANE_LIMITS_H], [
+AC_CACHE_CHECK([whether limits.h is sane],
+mfx_cv_header_sane_limits_h,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <limits.h>
+#if (32767 >= 4294967295ul) || (65535u >= 4294967295ul)
+# if defined(__APPLE__) && defined(__GNUC__)
+# error "your preprocessor is broken - use compiler option -no-cpp-precomp"
+# else
+# include "your preprocessor is broken"
+# endif
+#endif
+#define MFX_0xffff 0xffff
+#define MFX_0xffffffffL 4294967295ul
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+# include "error CHAR_BIT"
+#endif
+#if !defined(UCHAR_MAX)
+# include "error UCHAR_MAX 1"
+#endif
+#if !defined(USHRT_MAX)
+# include "error USHRT_MAX 1"
+#endif
+#if !defined(UINT_MAX)
+# include "error UINT_MAX 1"
+#endif
+#if !defined(ULONG_MAX)
+# include "error ULONG_MAX 1"
+#endif
+#if !defined(SHRT_MAX)
+# include "error SHRT_MAX 1"
+#endif
+#if !defined(INT_MAX)
+# include "error INT_MAX 1"
+#endif
+#if !defined(LONG_MAX)
+# include "error LONG_MAX 1"
+#endif
+#if (UCHAR_MAX < 1)
+# include "error UCHAR_MAX 2"
+#endif
+#if (USHRT_MAX < 1)
+# include "error USHRT_MAX 2"
+#endif
+#if (UINT_MAX < 1)
+# include "error UINT_MAX 2"
+#endif
+#if (ULONG_MAX < 1)
+# include "error ULONG_MAX 2"
+#endif
+#if (UCHAR_MAX < 0xff)
+# include "error UCHAR_MAX 3"
+#endif
+#if (USHRT_MAX < MFX_0xffff)
+# include "error USHRT_MAX 3"
+#endif
+#if (UINT_MAX < MFX_0xffff)
+# include "error UINT_MAX 3"
+#endif
+#if (ULONG_MAX < MFX_0xffffffffL)
+# include "error ULONG_MAX 3"
+#endif
+#if (USHRT_MAX > UINT_MAX)
+# include "error USHRT_MAX vs UINT_MAX"
+#endif
+#if (UINT_MAX > ULONG_MAX)
+# include "error UINT_MAX vs ULONG_MAX"
+#endif
+]], [[
+#if (USHRT_MAX == MFX_0xffff)
+{ typedef char a_short2a[1 - 2 * !(sizeof(short) == 2)]; }
+#elif (USHRT_MAX >= MFX_0xffff)
+{ typedef char a_short2b[1 - 2 * !(sizeof(short) > 2)]; }
+#endif
+#if (UINT_MAX == MFX_0xffff)
+{ typedef char a_int2a[1 - 2 * !(sizeof(int) == 2)]; }
+#elif (UINT_MAX >= MFX_0xffff)
+{ typedef char a_int2b[1 - 2 * !(sizeof(int) > 2)]; }
+#endif
+#if (ULONG_MAX == MFX_0xffff)
+{ typedef char a_long2a[1 - 2 * !(sizeof(long) == 2)]; }
+#elif (ULONG_MAX >= MFX_0xffff)
+{ typedef char a_long2b[1 - 2 * !(sizeof(long) > 2)]; }
+#endif
+#if !defined(_CRAY1) /* CRAY PVP systems */
+#if (USHRT_MAX == MFX_0xffffffffL)
+{ typedef char a_short4a[1 - 2 * !(sizeof(short) == 4)]; }
+#elif (USHRT_MAX >= MFX_0xffffffffL)
+{ typedef char a_short4b[1 - 2 * !(sizeof(short) > 4)]; }
+#endif
+#endif /* _CRAY1 */
+#if (UINT_MAX == MFX_0xffffffffL)
+{ typedef char a_int4a[1 - 2 * !(sizeof(int) == 4)]; }
+#elif (UINT_MAX >= MFX_0xffffffffL)
+{ typedef char a_int4b[1 - 2 * !(sizeof(int) > 4)]; }
+#endif
+#if (ULONG_MAX == MFX_0xffffffffL)
+{ typedef char a_long4a[1 - 2 * !(sizeof(long) == 4)]; }
+#elif (ULONG_MAX >= MFX_0xffffffffL)
+{ typedef char a_long4b[1 - 2 * !(sizeof(long) > 4)]; }
+#endif
+]])],
+[mfx_cv_header_sane_limits_h=yes],
+[mfx_cv_header_sane_limits_h=no])])
+])
+
+# /***********************************************************************
+# // standard
+# ************************************************************************/
+
+AC_DEFUN([mfx_LZO_CHECK_ENDIAN], [
+AC_C_BIGENDIAN([AC_DEFINE(LZO_ABI_BIG_ENDIAN,1,[Define to 1 if your machine is big endian.])],[AC_DEFINE(LZO_ABI_LITTLE_ENDIAN,1,[Define to 1 if your machine is little endian.])])
+])#
+
+
+# /***********************************************************************
+# //
+# ************************************************************************/
+
+dnl more types which are not yet covered by ACC
+
+AC_DEFUN([mfx_CHECK_SIZEOF], [
+AC_CHECK_SIZEOF(__int32)
+AC_CHECK_SIZEOF(intmax_t)
+AC_CHECK_SIZEOF(uintmax_t)
+AC_CHECK_SIZEOF(intptr_t)
+AC_CHECK_SIZEOF(uintptr_t)
+
+AC_CHECK_SIZEOF(float)
+AC_CHECK_SIZEOF(double)
+AC_CHECK_SIZEOF(long double)
+
+AC_CHECK_SIZEOF(dev_t)
+AC_CHECK_SIZEOF(fpos_t)
+AC_CHECK_SIZEOF(mode_t)
+AC_CHECK_SIZEOF(off_t)
+AC_CHECK_SIZEOF(ssize_t)
+AC_CHECK_SIZEOF(time_t)
+])#
+
+
+
+AC_DEFUN([mfx_CHECK_LIB_WINMM], [
+if test "X$GCC" = Xyes; then
+case $host_os in
+cygwin* | mingw* | pw32*)
+ test "X$LIBS" != "X" && LIBS="$LIBS "
+ LIBS="${LIBS}-lwinmm" ;;
+*)
+ ;;
+esac
+fi
+])#
diff --git a/tools/missing-macros/src/m4/progtest.m4 b/tools/missing-macros/src/m4/progtest.m4
new file mode 100644
index 0000000..2d804ac
--- /dev/null
+++ b/tools/missing-macros/src/m4/progtest.m4
@@ -0,0 +1,92 @@
+# progtest.m4 serial 6 (gettext-0.18)
+dnl Copyright (C) 1996-2003, 2005, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+AC_PREREQ([2.50])
+
+# Search path for a program which passes the given test.
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN([AM_PATH_PROG_WITH_TEST],
+[
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Find out how to test for executable files. Don't use a zero-byte file,
+# as systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+ ac_executable_p="test -x"
+else
+ ac_executable_p="test -f"
+fi
+rm -f conf$$.file
+
+# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL([ac_cv_path_$1],
+[case "[$]$1" in
+ [[\\/]]* | ?:[[\\/]]*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ IFS="$ac_save_IFS"
+ test -z "$ac_dir" && ac_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
+ echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
+ break 2
+ fi
+ fi
+ done
+ done
+ IFS="$ac_save_IFS"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
+ AC_MSG_RESULT([$][$1])
+else
+ AC_MSG_RESULT([no])
+fi
+AC_SUBST([$1])dnl
+])
diff --git a/tools/missing-macros/src/m4/stdint_h.m4 b/tools/missing-macros/src/m4/stdint_h.m4
new file mode 100644
index 0000000..b8e3c6c
--- /dev/null
+++ b/tools/missing-macros/src/m4/stdint_h.m4
@@ -0,0 +1,26 @@
+# stdint_h.m4 serial 8
+dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_STDINT_H],
+[
+ AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h],
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <stdint.h>],
+ [uintmax_t i = (uintmax_t) -1; return !i;],
+ [gl_cv_header_stdint_h=yes],
+ [gl_cv_header_stdint_h=no])])
+ if test $gl_cv_header_stdint_h = yes; then
+ AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1],
+ [Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
diff --git a/tools/missing-macros/src/m4/uintmax_t.m4 b/tools/missing-macros/src/m4/uintmax_t.m4
new file mode 100644
index 0000000..03b51bc
--- /dev/null
+++ b/tools/missing-macros/src/m4/uintmax_t.m4
@@ -0,0 +1,30 @@
+# uintmax_t.m4 serial 12
+dnl Copyright (C) 1997-2004, 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+AC_PREREQ([2.13])
+
+# Define uintmax_t to 'unsigned long' or 'unsigned long long'
+# if it is not already defined in <stdint.h> or <inttypes.h>.
+
+AC_DEFUN([gl_AC_TYPE_UINTMAX_T],
+[
+ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+ if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then
+ AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
+ test $ac_cv_type_unsigned_long_long_int = yes \
+ && ac_type='unsigned long long' \
+ || ac_type='unsigned long'
+ AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type],
+ [Define to unsigned long or unsigned long long
+ if <stdint.h> and <inttypes.h> don't define.])
+ else
+ AC_DEFINE([HAVE_UINTMAX_T], [1],
+ [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.])
+ fi
+])
diff --git a/tools/missing-macros/src/m4/va_copy.m4 b/tools/missing-macros/src/m4/va_copy.m4
new file mode 100644
index 0000000..0e88ee6
--- /dev/null
+++ b/tools/missing-macros/src/m4/va_copy.m4
@@ -0,0 +1,111 @@
+# va_copy.m4 serial 1 (js-1.6.20070208)
+
+dnl ##
+dnl ## Check for C99 va_copy() implementation
+dnl ## (and provide fallback implementation if neccessary)
+dnl ##
+dnl ## configure.in:
+dnl ## AC_CHECK_VA_COPY
+dnl ## foo.c:
+dnl ## #include "config.h"
+dnl ## [...]
+dnl ## va_copy(d,s)
+dnl ##
+dnl ## This check is rather complex: first because we really have to
+dnl ## try various possible implementations in sequence and second, we
+dnl ## cannot define a macro in config.h with parameters directly.
+dnl ##
+
+dnl # test program for va_copy() implementation
+changequote(<<,>>)
+m4_define(__va_copy_test, <<[
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#define DO_VA_COPY(d, s) $1
+void test(char *str, ...)
+{
+ va_list ap, ap2;
+ int i;
+ va_start(ap, str);
+ DO_VA_COPY(ap2, ap);
+ for (i = 1; i <= 9; i++) {
+ int k = (int)va_arg(ap, int);
+ if (k != i)
+ abort();
+ }
+ DO_VA_COPY(ap, ap2);
+ for (i = 1; i <= 9; i++) {
+ int k = (int)va_arg(ap, int);
+ if (k != i)
+ abort();
+ }
+ va_end(ap);
+}
+int main(int argc, char *argv[])
+{
+ test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ exit(0);
+}
+]>>)
+changequote([,])
+
+dnl # test driver for va_copy() implementation
+m4_define(__va_copy_check, [
+ AH_VERBATIM($1,
+[/* Predefined possible va_copy() implementation (id: $1) */
+#define __VA_COPY_USE_$1(d, s) $2])
+ if test ".$ac_cv_va_copy" = .; then
+ AC_TRY_RUN(__va_copy_test($2), [ac_cv_va_copy="$1"])
+ fi
+])
+
+dnl # Autoconf check for va_copy() implementation checking
+AC_DEFUN([AC_CHECK_VA_COPY],[
+ dnl # provide Autoconf display check message
+ AC_MSG_CHECKING(for va_copy() function)
+ dnl # check for various implementations in priorized sequence
+ AC_CACHE_VAL(ac_cv_va_copy, [
+ ac_cv_va_copy=""
+ dnl # 1. check for standardized C99 macro
+ __va_copy_check(C99, [va_copy((d), (s))])
+ dnl # 2. check for alternative/deprecated GCC macro
+ __va_copy_check(GCM, [VA_COPY((d), (s))])
+ dnl # 3. check for internal GCC macro (high-level define)
+ __va_copy_check(GCH, [__va_copy((d), (s))])
+ dnl # 4. check for internal GCC macro (built-in function)
+ __va_copy_check(GCB, [__builtin_va_copy((d), (s))])
+ dnl # 5. check for assignment approach (assuming va_list is a struct)
+ __va_copy_check(ASS, [do { (d) = (s); } while (0)])
+ dnl # 6. check for assignment approach (assuming va_list is a pointer)
+ __va_copy_check(ASP, [do { *(d) = *(s); } while (0)])
+ dnl # 7. check for memory copying approach (assuming va_list is a struct)
+ __va_copy_check(CPS, [memcpy((void *)&(d), (void *)&(s)), sizeof((s))])
+ dnl # 8. check for memory copying approach (assuming va_list is a pointer)
+ __va_copy_check(CPP, [memcpy((void *)(d), (void *)(s)), sizeof(*(s))])
+ if test ".$ac_cv_va_copy" = .; then
+ AC_ERROR([no working implementation found])
+ fi
+ ])
+ dnl # optionally activate the fallback implementation
+ if test ".$ac_cv_va_copy" = ".C99"; then
+ AC_DEFINE(HAVE_VA_COPY, 1, [Define if va_copy() macro exists (and no fallback implementation is required)])
+ fi
+ dnl # declare which fallback implementation to actually use
+ AC_DEFINE_UNQUOTED([__VA_COPY_USE], [__VA_COPY_USE_$ac_cv_va_copy],
+ [Define to id of used va_copy() implementation])
+ dnl # provide activation hook for fallback implementation
+ AH_VERBATIM([__VA_COPY_ACTIVATION],
+[/* Optional va_copy() implementation activation */
+#ifndef HAVE_VA_COPY
+#define va_copy(d, s) __VA_COPY_USE(d, s)
+#endif
+])
+ dnl # provide Autoconf display result message
+ if test ".$ac_cv_va_copy" = ".C99"; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no (using fallback implementation)])
+ fi
+])
+
diff --git a/tools/missing-macros/src/m4/wint_t.m4 b/tools/missing-macros/src/m4/wint_t.m4
new file mode 100644
index 0000000..a6c7d15
--- /dev/null
+++ b/tools/missing-macros/src/m4/wint_t.m4
@@ -0,0 +1,28 @@
+# wint_t.m4 serial 4 (gettext-0.18)
+dnl Copyright (C) 2003, 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether <wchar.h> has the 'wint_t' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_WINT_T],
+[
+ AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t],
+ [AC_TRY_COMPILE([
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included
+ before <wchar.h>. */
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+ wint_t foo = (wchar_t)'\0';], ,
+ [gt_cv_c_wint_t=yes], [gt_cv_c_wint_t=no])])
+ if test $gt_cv_c_wint_t = yes; then
+ AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.])
+ fi
+])
diff --git a/tools/mkimage/Makefile b/tools/mkimage/Makefile
new file mode 100644
index 0000000..f73cc56
--- /dev/null
+++ b/tools/mkimage/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mkimage
+PKG_VERSION:=2014.10
+
+PKG_SOURCE:=u-boot-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=\
+ http://mirror2.openwrt.org/sources \
+ ftp://ftp.denx.de/pub/u-boot
+PKG_MD5SUM:=3ddcaee2f05b7c464778112ec83664b5
+PKG_CAT:=bzcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/u-boot-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Prepare
+ $(Host/Prepare/Default)
+ rm -f \
+ $(HOST_BUILD_DIR)/include/errno.h \
+ $(HOST_BUILD_DIR)/include/malloc.h \
+ $(HOST_BUILD_DIR)/tools/.depend
+ touch $(HOST_BUILD_DIR)/include/config.mk
+ touch $(HOST_BUILD_DIR)/include/config.h
+endef
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) defconfig HOSTCFLAGS="$(HOST_CPPFLAGS) $(HOST_CFLAGS)" HOSTLDFLAGS="$(HOST_LDFLAGS)"
+ $(MAKE) -C $(HOST_BUILD_DIR) tools-only HOSTCFLAGS="$(HOST_CPPFLAGS) $(HOST_CFLAGS)" HOSTLDFLAGS="$(HOST_LDFLAGS)"
+endef
+
+define Host/Install
+ $(CP) $(HOST_BUILD_DIR)/tools/mkimage $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mkimage
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/mkimage/patches/010-freebsd-ulong-fix.patch b/tools/mkimage/patches/010-freebsd-ulong-fix.patch
new file mode 100644
index 0000000..75b9e89
--- /dev/null
+++ b/tools/mkimage/patches/010-freebsd-ulong-fix.patch
@@ -0,0 +1,13 @@
+--- a/include/image.h
++++ b/include/image.h
+@@ -44,6 +44,10 @@
+
+ #endif /* USE_HOSTCC */
+
++#ifndef ulong
++#define ulong unsigned long
++#endif
++
+ #if defined(CONFIG_FIT)
+ #include <hash.h>
+ #include <libfdt.h>
diff --git a/tools/mkimage/patches/020-include_compile_fix.patch b/tools/mkimage/patches/020-include_compile_fix.patch
new file mode 100644
index 0000000..276cae0
--- /dev/null
+++ b/tools/mkimage/patches/020-include_compile_fix.patch
@@ -0,0 +1,10 @@
+--- a/include/u-boot/rsa-checksum.h
++++ b/include/u-boot/rsa-checksum.h
+@@ -7,7 +7,6 @@
+ #ifndef _RSA_CHECKSUM_H
+ #define _RSA_CHECKSUM_H
+
+-#include <errno.h>
+ #include <image.h>
+ #include <u-boot/sha1.h>
+ #include <u-boot/sha256.h>
diff --git a/tools/mkimage/patches/030-allow-to-use-different-magic.patch b/tools/mkimage/patches/030-allow-to-use-different-magic.patch
new file mode 100644
index 0000000..d5afdd3
--- /dev/null
+++ b/tools/mkimage/patches/030-allow-to-use-different-magic.patch
@@ -0,0 +1,63 @@
+--- a/tools/mkimage.c
++++ b/tools/mkimage.c
+@@ -24,6 +24,7 @@
+ .arch = IH_ARCH_PPC,
+ .type = IH_TYPE_KERNEL,
+ .comp = IH_COMP_GZIP,
++ .magic = IH_MAGIC,
+ .dtc = MKIMAGE_DEFAULT_DTC_OPTIONS,
+ .imagename = "",
+ .imagename2 = "",
+@@ -168,6 +169,16 @@
+ genimg_get_comp_id (*++argv)) < 0)
+ usage ();
+ goto NXTARG;
++ case 'M':
++ if (--argc <=0)
++ usage ();
++ params.magic = strtoul (*++argv, &ptr, 16);
++ if (*ptr) {
++ fprintf (stderr,
++ "%s: invalid magic %s\n",
++ params.cmdname, *argv);
++ }
++ goto NXTARG;
+ case 'D':
+ if (--argc <= 0)
+ usage ();
+@@ -623,12 +634,13 @@
+ fprintf (stderr, "Usage: %s -l image\n"
+ " -l ==> list image header information\n",
+ params.cmdname);
+- fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp "
++ fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp -M magic "
+ "-a addr -e ep -n name -d data_file[:data_file...] image\n"
+ " -A ==> set architecture to 'arch'\n"
+ " -O ==> set operating system to 'os'\n"
+ " -T ==> set image type to 'type'\n"
+ " -C ==> set compression type 'comp'\n"
++ " -M ==> set image magic to 'magic'\n"
+ " -a ==> set load address to 'addr' (hex)\n"
+ " -e ==> set entry point to 'ep' (hex)\n"
+ " -n ==> set image name to 'name'\n"
+--- a/tools/default_image.c
++++ b/tools/default_image.c
+@@ -98,7 +98,7 @@
+ sbuf->st_size - sizeof(image_header_t));
+
+ /* Build new header */
+- image_set_magic(hdr, IH_MAGIC);
++ image_set_magic(hdr, params->magic);
+ image_set_time(hdr, sbuf->st_mtime);
+ image_set_size(hdr, sbuf->st_size - sizeof(image_header_t));
+ image_set_load(hdr, params->addr);
+--- a/tools/imagetool.h
++++ b/tools/imagetool.h
+@@ -44,6 +44,7 @@
+ int arch;
+ int type;
+ int comp;
++ unsigned int magic;
+ char *dtc;
+ unsigned int addr;
+ unsigned int ep;
diff --git a/tools/mkimage/patches/040-include_order.patch b/tools/mkimage/patches/040-include_order.patch
new file mode 100644
index 0000000..3b9ecc6
--- /dev/null
+++ b/tools/mkimage/patches/040-include_order.patch
@@ -0,0 +1,11 @@
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -194,7 +194,7 @@ endif # !LOGO_BMP
+ # Define _GNU_SOURCE to obtain the getline prototype from stdio.h
+ #
+ HOST_EXTRACFLAGS += -include $(srctree)/include/libfdt_env.h \
+- $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \
++ -I$(srctree)/include \
+ -I$(srctree)/lib/libfdt \
+ -I$(srctree)/tools \
+ -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \
diff --git a/tools/mkimage/patches/050-image_h_portability.patch b/tools/mkimage/patches/050-image_h_portability.patch
new file mode 100644
index 0000000..b3ad273
--- /dev/null
+++ b/tools/mkimage/patches/050-image_h_portability.patch
@@ -0,0 +1,31 @@
+--- a/include/image.h
++++ b/include/image.h
+@@ -17,7 +17,6 @@
+ #define __IMAGE_H__
+
+ #include "compiler.h"
+-#include <asm/byteorder.h>
+
+ /* Define this to avoid #ifdefs later on */
+ struct lmb;
+@@ -258,13 +257,13 @@ struct lmb;
+ * all data in network byte order (aka natural aka bigendian).
+ */
+ typedef struct image_header {
+- __be32 ih_magic; /* Image Header Magic Number */
+- __be32 ih_hcrc; /* Image Header CRC Checksum */
+- __be32 ih_time; /* Image Creation Timestamp */
+- __be32 ih_size; /* Image Data Size */
+- __be32 ih_load; /* Data Load Address */
+- __be32 ih_ep; /* Entry Point Address */
+- __be32 ih_dcrc; /* Image Data CRC Checksum */
++ uint32_t ih_magic; /* Image Header Magic Number */
++ uint32_t ih_hcrc; /* Image Header CRC Checksum */
++ uint32_t ih_time; /* Image Creation Timestamp */
++ uint32_t ih_size; /* Image Data Size */
++ uint32_t ih_load; /* Data Load Address */
++ uint32_t ih_ep; /* Entry Point Address */
++ uint32_t ih_dcrc; /* Image Data CRC Checksum */
+ uint8_t ih_os; /* Operating System */
+ uint8_t ih_arch; /* CPU architecture */
+ uint8_t ih_type; /* Image Type */
diff --git a/tools/mkimage/patches/060-remove_kernel_includes.patch b/tools/mkimage/patches/060-remove_kernel_includes.patch
new file mode 100644
index 0000000..fa533cd
--- /dev/null
+++ b/tools/mkimage/patches/060-remove_kernel_includes.patch
@@ -0,0 +1,35 @@
+--- a/include/compiler.h
++++ b/include/compiler.h
+@@ -58,6 +58,11 @@ typedef uint8_t __u8;
+ typedef uint16_t __u16;
+ typedef uint32_t __u32;
+ typedef unsigned int uint;
++typedef uint64_t __u64;
++#ifndef linux
++typedef int __kernel_daddr_t;
++typedef unsigned int __kernel_ino_t;
++#endif
+
+ #define uswap_16(x) \
+ ((((x) & 0xff00) >> 8) | \
+--- a/include/linux/posix_types.h
++++ b/include/linux/posix_types.h
+@@ -43,6 +43,8 @@ typedef void (*__kernel_sighandler_t)(in
+ /* Type of a SYSV IPC key. */
+ typedef int __kernel_key_t;
+
++#ifdef linux
+ #include <asm/posix_types.h>
++#endif
+
+ #endif /* _LINUX_POSIX_TYPES_H */
+--- a/include/linux/types.h
++++ b/include/linux/types.h
+@@ -2,7 +2,6 @@
+ #define _LINUX_TYPES_H
+
+ #include <linux/posix_types.h>
+-#include <asm/types.h>
+ #include <stdbool.h>
+
+ #ifndef __KERNEL_STRICT_NAMES
diff --git a/tools/mkimage/patches/070-socfpgaimage_portability.patch b/tools/mkimage/patches/070-socfpgaimage_portability.patch
new file mode 100644
index 0000000..e273c27
--- /dev/null
+++ b/tools/mkimage/patches/070-socfpgaimage_portability.patch
@@ -0,0 +1,52 @@
+--- a/tools/socfpgaimage.c
++++ b/tools/socfpgaimage.c
+@@ -74,12 +74,12 @@ static uint16_t hdr_checksum(struct socf
+ static void build_header(uint8_t *buf, uint8_t version, uint8_t flags,
+ uint16_t length_bytes)
+ {
+- header.validation = htole32(VALIDATION_WORD);
++ header.validation = cpu_to_le32(VALIDATION_WORD);
+ header.version = version;
+ header.flags = flags;
+- header.length_u32 = htole16(length_bytes/4);
++ header.length_u32 = cpu_to_le16(length_bytes/4);
+ header.zero = 0;
+- header.checksum = htole16(hdr_checksum(&header));
++ header.checksum = cpu_to_le16(hdr_checksum(&header));
+
+ memcpy(buf, &header, sizeof(header));
+ }
+@@ -92,12 +92,12 @@ static int verify_header(const uint8_t *
+ {
+ memcpy(&header, buf, sizeof(header));
+
+- if (le32toh(header.validation) != VALIDATION_WORD)
++ if (le32_to_cpu(header.validation) != VALIDATION_WORD)
+ return -1;
+- if (le16toh(header.checksum) != hdr_checksum(&header))
++ if (le16_to_cpu(header.checksum) != hdr_checksum(&header))
+ return -1;
+
+- return le16toh(header.length_u32) * 4;
++ return le16_to_cpu(header.length_u32) * 4;
+ }
+
+ /* Sign the buffer and return the signed buffer size */
+@@ -116,7 +116,7 @@ static int sign_buffer(uint8_t *buf,
+ /* Calculate and apply the CRC */
+ calc_crc = ~pbl_crc32(0, (char *)buf, len);
+
+- *((uint32_t *)(buf + len)) = htole32(calc_crc);
++ *((uint32_t *)(buf + len)) = cpu_to_le32(calc_crc);
+
+ if (!pad_64k)
+ return len + 4;
+@@ -150,7 +150,7 @@ static int verify_buffer(const uint8_t *
+
+ calc_crc = ~pbl_crc32(0, (const char *)buf, len);
+
+- buf_crc = le32toh(*((uint32_t *)(buf + len)));
++ buf_crc = le32_to_cpu(*((uint32_t *)(buf + len)));
+
+ if (buf_crc != calc_crc) {
+ fprintf(stderr, "CRC32 does not match (%08x != %08x)\n",
diff --git a/tools/mkimage/patches/080-remove_compiler_check.patch b/tools/mkimage/patches/080-remove_compiler_check.patch
new file mode 100644
index 0000000..3e71ad5
--- /dev/null
+++ b/tools/mkimage/patches/080-remove_compiler_check.patch
@@ -0,0 +1,16 @@
+--- a/include/linux/compiler-gcc4.h
++++ b/include/linux/compiler-gcc4.h
+@@ -2,13 +2,6 @@
+ #error "Please don't include <linux/compiler-gcc4.h> directly, include <linux/compiler.h> instead."
+ #endif
+
+-/* GCC 4.1.[01] miscompiles __weak */
+-#ifdef __KERNEL__
+-# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101
+-# error Your version of gcc miscompiles the __weak directive
+-# endif
+-#endif
+-
+ #define __used __attribute__((__used__))
+ #define __must_check __attribute__((warn_unused_result))
+ #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
diff --git a/tools/mkimage/patches/100-freebsd-compat.patch b/tools/mkimage/patches/100-freebsd-compat.patch
new file mode 100644
index 0000000..e014af5
--- /dev/null
+++ b/tools/mkimage/patches/100-freebsd-compat.patch
@@ -0,0 +1,14 @@
+--- a/Makefile
++++ b/Makefile
+@@ -584,7 +584,10 @@ UBOOTINCLUDE := \
+ -I$(srctree)/arch/$(ARCH)/include \
+ -include $(srctree)/include/linux/kconfig.h
+
+-NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
++ifneq ($(shell uname),FreeBSD)
++ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
++endif
++
+ CHECKFLAGS += $(NOSTDINC_FLAGS)
+
+ # FIX ME
diff --git a/tools/mkimage/patches/200-gcc5_compat.patch b/tools/mkimage/patches/200-gcc5_compat.patch
new file mode 100644
index 0000000..4d55f00
--- /dev/null
+++ b/tools/mkimage/patches/200-gcc5_compat.patch
@@ -0,0 +1,93 @@
+From 478b02f1a7043b673565075ea5016376f3293b23 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 7 Feb 2015 22:52:40 +0100
+Subject: [PATCH] Add linux/compiler-gcc5.h to fix builds with gcc5
+
+Add linux/compiler-gcc5/h from the kernel sources at:
+
+commit 5631b8fba640a4ab2f8a954f63a603fa34eda96b
+Author: Steven Noonan <steven@uplinklabs.net>
+Date: Sat Oct 25 15:09:42 2014 -0700
+
+ compiler/gcc4+: Remove inaccurate comment about 'asm goto' miscompiles
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ include/linux/compiler-gcc5.h | 65 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 65 insertions(+)
+ create mode 100644 include/linux/compiler-gcc5.h
+
+diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h
+new file mode 100644
+index 0000000..c8c5659
+--- /dev/null
++++ b/include/linux/compiler-gcc5.h
+@@ -0,0 +1,65 @@
++#ifndef __LINUX_COMPILER_H
++#error "Please don't include <linux/compiler-gcc5.h> directly, include <linux/compiler.h> instead."
++#endif
++
++#define __used __attribute__((__used__))
++#define __must_check __attribute__((warn_unused_result))
++#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
++
++/* Mark functions as cold. gcc will assume any path leading to a call
++ to them will be unlikely. This means a lot of manual unlikely()s
++ are unnecessary now for any paths leading to the usual suspects
++ like BUG(), printk(), panic() etc. [but let's keep them for now for
++ older compilers]
++
++ Early snapshots of gcc 4.3 don't support this and we can't detect this
++ in the preprocessor, but we can live with this because they're unreleased.
++ Maketime probing would be overkill here.
++
++ gcc also has a __attribute__((__hot__)) to move hot functions into
++ a special section, but I don't see any sense in this right now in
++ the kernel context */
++#define __cold __attribute__((__cold__))
++
++#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
++
++#ifndef __CHECKER__
++# define __compiletime_warning(message) __attribute__((warning(message)))
++# define __compiletime_error(message) __attribute__((error(message)))
++#endif /* __CHECKER__ */
++
++/*
++ * Mark a position in code as unreachable. This can be used to
++ * suppress control flow warnings after asm blocks that transfer
++ * control elsewhere.
++ *
++ * Early snapshots of gcc 4.5 don't support this and we can't detect
++ * this in the preprocessor, but we can live with this because they're
++ * unreleased. Really, we need to have autoconf for the kernel.
++ */
++#define unreachable() __builtin_unreachable()
++
++/* Mark a function definition as prohibited from being cloned. */
++#define __noclone __attribute__((__noclone__))
++
++/*
++ * Tell the optimizer that something else uses this function or variable.
++ */
++#define __visible __attribute__((externally_visible))
++
++/*
++ * GCC 'asm goto' miscompiles certain code sequences:
++ *
++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
++ *
++ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
++ *
++ * (asm goto is automatically volatile - the naming reflects this.)
++ */
++#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
++
++#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
++#define __HAVE_BUILTIN_BSWAP32__
++#define __HAVE_BUILTIN_BSWAP64__
++#define __HAVE_BUILTIN_BSWAP16__
++#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
+--
+1.7.10.4
+
diff --git a/tools/mklibs/Makefile b/tools/mklibs/Makefile
new file mode 100644
index 0000000..6bf1431
--- /dev/null
+++ b/tools/mklibs/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2009-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mklibs
+PKG_VERSION:=0.1.35
+
+PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://ftp.de.debian.org/debian/pool/main/m/mklibs/
+PKG_MD5SUM:=3d2a4bd0bbf5ba964b0a1ecdafd1ea9a
+
+HOST_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CFLAGS += -I$(CURDIR)/include
+
+define Host/Install
+ $(INSTALL_BIN) \
+ $(HOST_BUILD_DIR)/src/mklibs \
+ $(HOST_BUILD_DIR)/src/mklibs-copy \
+ $(HOST_BUILD_DIR)/src/mklibs-readelf/mklibs-readelf \
+ $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mklibs*
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/mklibs/include/elf.h b/tools/mklibs/include/elf.h
new file mode 100644
index 0000000..d796350
--- /dev/null
+++ b/tools/mklibs/include/elf.h
@@ -0,0 +1,2559 @@
+/* This file defines standard ELF types, structures, and macros.
+ Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _ELF_H
+#define _ELF_H 1
+
+__BEGIN_DECLS
+
+/* Standard ELF types. */
+
+#include <stdint.h>
+
+/* Type for a 16-bit quantity. */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities. */
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities. */
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+/* Type of addresses. */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets. */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities. */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information. */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header. This appears at the start of every ELF file. */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf64_Half e_type; /* Object file type */
+ Elf64_Half e_machine; /* Architecture */
+ Elf64_Word e_version; /* Object file version */
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ Elf64_Word e_flags; /* Processor-specific flags */
+ Elf64_Half e_ehsize; /* ELF header size in bytes */
+ Elf64_Half e_phentsize; /* Program header table entry size */
+ Elf64_Half e_phnum; /* Program header table entry count */
+ Elf64_Half e_shentsize; /* Section header table entry size */
+ Elf64_Half e_shnum; /* Section header table entry count */
+ Elf64_Half e_shstrndx; /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array. The EI_* macros are indices into the
+ array. The macros under each EI_* macro are the values the byte
+ may have. */
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7f /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word. */
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+#define ELFCLASSNUM 3
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+#define ELFDATANUM 3
+
+#define EI_VERSION 6 /* File version byte index */
+ /* Value must be EV_CURRENT */
+
+#define EI_OSABI 7 /* OS ABI identification */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_SYSV 0 /* Alias. */
+#define ELFOSABI_HPUX 1 /* HP-UX */
+#define ELFOSABI_NETBSD 2 /* NetBSD. */
+#define ELFOSABI_LINUX 3 /* Linux. */
+#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
+#define ELFOSABI_AIX 7 /* IBM AIX. */
+#define ELFOSABI_IRIX 8 /* SGI Irix. */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
+#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define EI_ABIVERSION 8 /* ABI version */
+
+#define EI_PAD 9 /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type). */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_NUM 5 /* Number of defined types */
+#define ET_LOOS 0xfe00 /* OS-specific range start */
+#define ET_HIOS 0xfeff /* OS-specific range end */
+#define ET_LOPROC 0xff00 /* Processor-specific range start */
+#define ET_HIPROC 0xffff /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture). */
+
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_NUM 95
+
+/* If it is necessary to assign new unofficial EM_* values, please
+ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+ chances of collision with official or non-GNU unofficial values. */
+
+#define EM_ALPHA 0x9026
+
+/* Legal values for e_version (version). */
+
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+#define EV_NUM 2
+
+/* Section header. */
+
+typedef struct
+{
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf64_Word sh_name; /* Section name (string tbl index) */
+ Elf64_Word sh_type; /* Section type */
+ Elf64_Xword sh_flags; /* Section flags */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Xword sh_size; /* Section size in bytes */
+ Elf64_Word sh_link; /* Link to another section */
+ Elf64_Word sh_info; /* Additional section information */
+ Elf64_Xword sh_addralign; /* Section alignment */
+ Elf64_Xword sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices. */
+
+#define SHN_UNDEF 0 /* Undefined section */
+#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
+#define SHN_LOPROC 0xff00 /* Start of processor-specific */
+#define SHN_BEFORE 0xff00 /* Order section before all others
+ (Solaris). */
+#define SHN_AFTER 0xff01 /* Order section after all others
+ (Solaris). */
+#define SHN_HIPROC 0xff1f /* End of processor-specific */
+#define SHN_LOOS 0xff20 /* Start of OS-specific */
+#define SHN_HIOS 0xff3f /* End of OS-specific */
+#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
+#define SHN_COMMON 0xfff2 /* Associated symbol is common */
+#define SHN_XINDEX 0xffff /* Index is in extra table. */
+#define SHN_HIRESERVE 0xffff /* End of reserved indices */
+
+/* Legal values for sh_type (section type). */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program data */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Notes */
+#define SHT_NOBITS 8 /* Program space with no data (bss) */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY 14 /* Array of constructors */
+#define SHT_FINI_ARRAY 15 /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
+#define SHT_GROUP 17 /* Section group */
+#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
+#define SHT_NUM 19 /* Number of defined types. */
+#define SHT_LOOS 0x60000000 /* Start OS-specific */
+#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
+#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
+#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
+#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
+#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
+#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
+#define SHT_HIOS 0x6fffffff /* End OS-specific type */
+#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
+#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
+#define SHT_LOUSER 0x80000000 /* Start of application-specific */
+#define SHT_HIUSER 0x8fffffff /* End of application-specific */
+
+/* Legal values for sh_flags (section flags). */
+
+#define SHF_WRITE (1 << 0) /* Writable */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable */
+#define SHF_MERGE (1 << 4) /* Might be merged */
+#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
+#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
+ required */
+#define SHF_GROUP (1 << 9) /* Section is member of a group. */
+#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
+#define SHF_ORDERED (1 << 30) /* Special ordering requirement
+ (Solaris). */
+#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
+ referenced or allocated (Solaris).*/
+
+/* Section group handling. */
+#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
+
+/* Symbol table entry. */
+
+typedef struct
+{
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+ Elf64_Word st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf64_Section st_shndx; /* Section index */
+ Elf64_Addr st_value; /* Symbol value */
+ Elf64_Xword st_size; /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+ every dynamic symbol. */
+
+typedef struct
+{
+ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf32_Half si_flags; /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf64_Half si_flags; /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto. */
+#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags. */
+#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
+ loaded */
+/* Syminfo version values. */
+#define SYMINFO_NONE 0
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+
+/* How to extract and insert information held in the st_info field. */
+
+#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val) ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
+#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding). */
+
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* Weak symbol */
+#define STB_NUM 3 /* Number of defined types. */
+#define STB_LOOS 10 /* Start of OS-specific */
+#define STB_HIOS 12 /* End of OS-specific */
+#define STB_LOPROC 13 /* Start of processor-specific */
+#define STB_HIPROC 15 /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol's name is file name */
+#define STT_COMMON 5 /* Symbol is a common data object */
+#define STT_TLS 6 /* Symbol is thread-local data object*/
+#define STT_NUM 7 /* Number of defined types. */
+#define STT_LOOS 10 /* Start of OS-specific */
+#define STT_HIOS 12 /* End of OS-specific */
+#define STT_LOPROC 13 /* Start of processor-specific */
+#define STT_HIPROC 15 /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+ of a symbol hash table section. This special index value indicates
+ the end of a chain, meaning no further symbols are found in that bucket. */
+
+#define STN_UNDEF 0 /* End of a chain. */
+
+
+/* How to extract and insert information held in the st_other field. */
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+
+/* For ELF64 the definitions are the same. */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field. */
+#define STV_DEFAULT 0 /* Default symbol visibility rules */
+#define STV_INTERNAL 1 /* Processor specific hidden class */
+#define STV_HIDDEN 2 /* Sym unavailable in other modules */
+#define STV_PROTECTED 3 /* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+ Elf64_Rela structures, so we'll leave them out until Novell (or
+ whoever) gets their act together. */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+ Elf32_Sword r_addend; /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field. */
+
+#define ELF32_R_SYM(val) ((val) >> 8)
+#define ELF32_R_TYPE(val) ((val) & 0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header. */
+
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+ Elf64_Word p_type; /* Segment type */
+ Elf64_Word p_flags; /* Segment flags */
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Xword p_filesz; /* Segment size in file */
+ Elf64_Xword p_memsz; /* Segment size in memory */
+ Elf64_Xword p_align; /* Segment alignment */
+} Elf64_Phdr;
+
+/* Legal values for p_type (segment type). */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_TLS 7 /* Thread-local storage segment */
+#define PT_NUM 8 /* Number of defined types */
+#define PT_LOOS 0x60000000 /* Start of OS-specific */
+#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* End of OS-specific */
+#define PT_LOPROC 0x70000000 /* Start of processor-specific */
+#define PT_HIPROC 0x7fffffff /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags). */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKOS 0x0ff00000 /* OS-specific */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+#define NT_PRXREG 4 /* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
+#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV 6 /* Contains copy of auxv array */
+#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
+#define NT_ASRS 8 /* Contains copy of asrset struct */
+#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
+#define NT_PSINFO 13 /* Contains copy of psinfo struct */
+#define NT_PRCRED 14 /* Contains copy of prcred struct */
+#define NT_UTSNAME 15 /* Contains copy of utsname struct */
+#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/
+
+/* Legal values for the note segment descriptor types for object files. */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+
+/* Dynamic section entry. */
+
+typedef struct
+{
+ Elf32_Sword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf32_Word d_val; /* Integer value */
+ Elf32_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type). */
+
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_NEEDED 1 /* Name of needed library */
+#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
+#define DT_PLTGOT 3 /* Processor defined value */
+#define DT_HASH 4 /* Address of symbol hash table */
+#define DT_STRTAB 5 /* Address of string table */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+#define DT_STRSZ 10 /* Size of string table */
+#define DT_SYMENT 11 /* Size of one symbol table entry */
+#define DT_INIT 12 /* Address of init function */
+#define DT_FINI 13 /* Address of termination function */
+#define DT_SONAME 14 /* Name of shared object */
+#define DT_RPATH 15 /* Library search path (deprecated) */
+#define DT_SYMBOLIC 16 /* Start symbol search here */
+#define DT_REL 17 /* Address of Rel relocs */
+#define DT_RELSZ 18 /* Total size of Rel relocs */
+#define DT_RELENT 19 /* Size of one Rel reloc */
+#define DT_PLTREL 20 /* Type of reloc in PLT */
+#define DT_DEBUG 21 /* For debugging; unspecified */
+#define DT_TEXTREL 22 /* Reloc might modify .text */
+#define DT_JMPREL 23 /* Address of PLT relocs */
+#define DT_BIND_NOW 24 /* Process relocations of object */
+#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
+#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH 29 /* Library search path */
+#define DT_FLAGS 30 /* Flags for the object being loaded */
+#define DT_ENCODING 32 /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
+#define DT_NUM 34 /* Number used */
+#define DT_LOOS 0x6000000d /* Start of OS-specific */
+#define DT_HIOS 0x6ffff000 /* End of OS-specific */
+#define DT_LOPROC 0x70000000 /* Start of processor-specific */
+#define DT_HIPROC 0x7fffffff /* End of processor-specific */
+#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
+ approach. */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
+#define DT_CHECKSUM 0x6ffffdf8
+#define DT_PLTPADSZ 0x6ffffdf9
+#define DT_MOVEENT 0x6ffffdfa
+#define DT_MOVESZ 0x6ffffdfb
+#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
+#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
+ the following DT_* entry. */
+#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
+#define DT_VALRNGHI 0x6ffffdff
+#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+ If any adjustment is made to the ELF object after it has been
+ built these entries will need to be adjusted. */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
+#define DT_CONFIG 0x6ffffefa /* Configuration information. */
+#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
+#define DT_AUDIT 0x6ffffefc /* Object auditing. */
+#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
+#define DT_MOVETAB 0x6ffffefe /* Move table. */
+#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
+#define DT_ADDRRNGHI 0x6ffffeff
+#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
+#define DT_ADDRNUM 10
+
+/* The versioning entry types. The next are defined as part of the
+ GNU extension. */
+#define DT_VERSYM 0x6ffffff0
+
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+
+/* These were chosen by Sun. */
+#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
+#define DT_VERDEF 0x6ffffffc /* Address of version definition
+ table */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
+#define DT_VERNEED 0x6ffffffe /* Address of table with needed
+ versions */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+ range. Be compatible. */
+#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
+#define DT_FILTER 0x7fffffff /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM 3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry. */
+#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
+#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
+#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
+#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+ entry in the dynamic section. */
+#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
+#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
+#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
+#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
+#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
+#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
+#define DF_1_TRANS 0x00000200
+#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
+#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
+#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */
+#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */
+#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */
+#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */
+
+/* Flags for the feature selection in DT_FEATURE_1. */
+#define DTF_1_PARINIT 0x00000001
+#define DTF_1_CONFEXP 0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
+#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
+#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
+ generally available. */
+
+/* Version definition sections. */
+
+typedef struct
+{
+ Elf32_Half vd_version; /* Version revision */
+ Elf32_Half vd_flags; /* Version information */
+ Elf32_Half vd_ndx; /* Version Index */
+ Elf32_Half vd_cnt; /* Number of associated aux entries */
+ Elf32_Word vd_hash; /* Version name hash value */
+ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf32_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+ Elf64_Half vd_version; /* Version revision */
+ Elf64_Half vd_flags; /* Version information */
+ Elf64_Half vd_ndx; /* Version Index */
+ Elf64_Half vd_cnt; /* Number of associated aux entries */
+ Elf64_Word vd_hash; /* Version name hash value */
+ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf64_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision). */
+#define VER_DEF_NONE 0 /* No version */
+#define VER_DEF_CURRENT 1 /* Current version */
+#define VER_DEF_NUM 2 /* Given version number */
+
+/* Legal values for vd_flags (version information flags). */
+#define VER_FLG_BASE 0x1 /* Version definition of file itself */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+/* Versym symbol index values. */
+#define VER_NDX_LOCAL 0 /* Symbol is local. */
+#define VER_NDX_GLOBAL 1 /* Symbol is global. */
+#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
+#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
+
+/* Auxialiary version information. */
+
+typedef struct
+{
+ Elf32_Word vda_name; /* Version or dependency names */
+ Elf32_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+ Elf64_Word vda_name; /* Version or dependency names */
+ Elf64_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section. */
+
+typedef struct
+{
+ Elf32_Half vn_version; /* Version of structure */
+ Elf32_Half vn_cnt; /* Number of associated aux entries */
+ Elf32_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf32_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+ Elf64_Half vn_version; /* Version of structure */
+ Elf64_Half vn_cnt; /* Number of associated aux entries */
+ Elf64_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf64_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision). */
+#define VER_NEED_NONE 0 /* No version */
+#define VER_NEED_CURRENT 1 /* Current version */
+#define VER_NEED_NUM 2 /* Given version number */
+
+/* Auxiliary needed version information. */
+
+typedef struct
+{
+ Elf32_Word vna_hash; /* Hash value of dependency name */
+ Elf32_Half vna_flags; /* Dependency specific information */
+ Elf32_Half vna_other; /* Unused */
+ Elf32_Word vna_name; /* Dependency name string offset */
+ Elf32_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+ Elf64_Word vna_hash; /* Hash value of dependency name */
+ Elf64_Half vna_flags; /* Dependency specific information */
+ Elf64_Half vna_other; /* Unused */
+ Elf64_Word vna_name; /* Dependency name string offset */
+ Elf64_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags. */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+
+/* Auxiliary vector. */
+
+/* This vector is normally only used by the program interpreter. The
+ usual definition in an ABI supplement uses the name auxv_t. The
+ vector is not usually defined in a standard <elf.h> file, but it
+ can't hurt. We rename it to avoid conflicts. The sizes of these
+ types are an arrangement between the exec server and the program
+ interpreter, so we don't fully specify them here. */
+
+typedef struct
+{
+ int a_type; /* Entry type */
+ union
+ {
+ long int a_val; /* Integer value */
+ void *a_ptr; /* Pointer value */
+ void (*a_fcn) (void); /* Function pointer value */
+ } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+ long int a_type; /* Entry type */
+ union
+ {
+ long int a_val; /* Integer value */
+ void *a_ptr; /* Pointer value */
+ void (*a_fcn) (void); /* Function pointer value */
+ } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type). */
+
+#define AT_NULL 0 /* End of vector */
+#define AT_IGNORE 1 /* Entry should be ignored */
+#define AT_EXECFD 2 /* File descriptor of program */
+#define AT_PHDR 3 /* Program headers for program */
+#define AT_PHENT 4 /* Size of program header entry */
+#define AT_PHNUM 5 /* Number of program headers */
+#define AT_PAGESZ 6 /* System page size */
+#define AT_BASE 7 /* Base address of interpreter */
+#define AT_FLAGS 8 /* Flags */
+#define AT_ENTRY 9 /* Entry point of program */
+#define AT_NOTELF 10 /* Program is not ELF */
+#define AT_UID 11 /* Real uid */
+#define AT_EUID 12 /* Effective uid */
+#define AT_GID 13 /* Real gid */
+#define AT_EGID 14 /* Effective gid */
+#define AT_CLKTCK 17 /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware. */
+#define AT_PLATFORM 15 /* String identifying platform. */
+#define AT_HWCAP 16 /* Machine dependent hints about
+ processor capabilities. */
+
+/* This entry gives some information about the FPU initialization
+ performed by the kernel. */
+#define AT_FPUCW 18 /* Used FPU control word. */
+
+/* Cache block sizes. */
+#define AT_DCACHEBSIZE 19 /* Data cache block size. */
+#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */
+#define AT_UCACHEBSIZE 21 /* Unified cache block size. */
+
+/* A special ignored value for PPC, used by the kernel to control the
+ interpretation of the AUXV. Must be > 16. */
+#define AT_IGNOREPPC 22 /* Entry should be ignored. */
+
+#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
+
+/* Pointer to the global system page used for system calls and other
+ nice things. */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
+ log2 of line size; mask those to get cache size. */
+#define AT_L1I_CACHESHAPE 34
+#define AT_L1D_CACHESHAPE 35
+#define AT_L2_CACHESHAPE 36
+#define AT_L3_CACHESHAPE 37
+
+/* Note section contents. Each entry in the note section begins with
+ a header of a fixed form. */
+
+typedef struct
+{
+ Elf32_Word n_namesz; /* Length of the note's name. */
+ Elf32_Word n_descsz; /* Length of the note's descriptor. */
+ Elf32_Word n_type; /* Type of the note. */
+} Elf32_Nhdr;
+
+typedef struct
+{
+ Elf64_Word n_namesz; /* Length of the note's name. */
+ Elf64_Word n_descsz; /* Length of the note's descriptor. */
+ Elf64_Word n_type; /* Type of the note. */
+} Elf64_Nhdr;
+
+/* Known names of notes. */
+
+/* Solaris entries in the note section have this name. */
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+
+/* Note entries for GNU systems have this name. */
+#define ELF_NOTE_GNU "GNU"
+
+
+/* Defined types of notes for Solaris. */
+
+/* Value of descriptor (one word) is desired pagesize for the binary. */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+/* Defined note types for GNU systems. */
+
+/* ABI information. The descriptor consists of words:
+ word 0: OS descriptor
+ word 1: major version of the ABI
+ word 2: minor version of the ABI
+ word 3: subminor version of the ABI
+*/
+#define ELF_NOTE_ABI 1
+
+/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI
+ note section entry. */
+#define ELF_NOTE_OS_LINUX 0
+#define ELF_NOTE_OS_GNU 1
+#define ELF_NOTE_OS_SOLARIS2 2
+#define ELF_NOTE_OS_FREEBSD 3
+
+
+/* Move records. */
+typedef struct
+{
+ Elf32_Xword m_value; /* Symbol value. */
+ Elf32_Word m_info; /* Size and index. */
+ Elf32_Word m_poffset; /* Symbol offset. */
+ Elf32_Half m_repeat; /* Repeat count. */
+ Elf32_Half m_stride; /* Stride info. */
+} Elf32_Move;
+
+typedef struct
+{
+ Elf64_Xword m_value; /* Symbol value. */
+ Elf64_Xword m_info; /* Size and index. */
+ Elf64_Xword m_poffset; /* Symbol offset. */
+ Elf64_Half m_repeat; /* Repeat count. */
+ Elf64_Half m_stride; /* Stride info. */
+} Elf64_Move;
+
+/* Macro to construct move records. */
+#define ELF32_M_SYM(info) ((info) >> 8)
+#define ELF32_M_SIZE(info) ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info) ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions. */
+
+/* Values for Elf32_Ehdr.e_flags. */
+#define EF_CPU32 0x00810000
+
+/* m68k relocs. */
+
+#define R_68K_NONE 0 /* No reloc */
+#define R_68K_32 1 /* Direct 32 bit */
+#define R_68K_16 2 /* Direct 16 bit */
+#define R_68K_8 3 /* Direct 8 bit */
+#define R_68K_PC32 4 /* PC relative 32 bit */
+#define R_68K_PC16 5 /* PC relative 16 bit */
+#define R_68K_PC8 6 /* PC relative 8 bit */
+#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
+#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
+#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O 10 /* 32 bit GOT offset */
+#define R_68K_GOT16O 11 /* 16 bit GOT offset */
+#define R_68K_GOT8O 12 /* 8 bit GOT offset */
+#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
+#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
+#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
+#define R_68K_PLT32O 16 /* 32 bit PLT offset */
+#define R_68K_PLT16O 17 /* 16 bit PLT offset */
+#define R_68K_PLT8O 18 /* 8 bit PLT offset */
+#define R_68K_COPY 19 /* Copy symbol at runtime */
+#define R_68K_GLOB_DAT 20 /* Create GOT entry */
+#define R_68K_JMP_SLOT 21 /* Create PLT entry */
+#define R_68K_RELATIVE 22 /* Adjust by program base */
+/* Keep this the last entry. */
+#define R_68K_NUM 23
+
+/* Intel 80386 specific definitions. */
+
+/* i386 relocs. */
+
+#define R_386_NONE 0 /* No reloc */
+#define R_386_32 1 /* Direct 32 bit */
+#define R_386_PC32 2 /* PC relative 32 bit */
+#define R_386_GOT32 3 /* 32 bit GOT entry */
+#define R_386_PLT32 4 /* 32 bit PLT address */
+#define R_386_COPY 5 /* Copy symbol at runtime */
+#define R_386_GLOB_DAT 6 /* Create GOT entry */
+#define R_386_JMP_SLOT 7 /* Create PLT entry */
+#define R_386_RELATIVE 8 /* Adjust by program base */
+#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
+#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
+#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
+ block offset */
+#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block
+ offset */
+#define R_386_TLS_LE 17 /* Offset relative to static TLS
+ block */
+#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of
+ general dynamic thread local data */
+#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of
+ local dynamic thread local data
+ in LE code */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic
+ thread local data */
+#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL 26 /* Relocation for call to
+ __tls_get_addr() */
+#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic
+ thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30 /* Relocation for call to
+ __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
+#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS
+ block offset */
+#define R_386_TLS_LE_32 34 /* Negated offset relative to static
+ TLS block */
+#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
+#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
+/* Keep this the last entry. */
+#define R_386_NUM 38
+
+/* SUN SPARC specific definitions. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags. */
+
+#define EF_SPARCV9_MM 3
+#define EF_SPARCV9_TSO 0
+#define EF_SPARCV9_PSO 1
+#define EF_SPARCV9_RMO 2
+#define EF_SPARC_LEDATA 0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK 0xFFFF00
+#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs. */
+
+#define R_SPARC_NONE 0 /* No reloc */
+#define R_SPARC_8 1 /* Direct 8 bit */
+#define R_SPARC_16 2 /* Direct 16 bit */
+#define R_SPARC_32 3 /* Direct 32 bit */
+#define R_SPARC_DISP8 4 /* PC relative 8 bit */
+#define R_SPARC_DISP16 5 /* PC relative 16 bit */
+#define R_SPARC_DISP32 6 /* PC relative 32 bit */
+#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
+#define R_SPARC_HI22 9 /* High 22 bit */
+#define R_SPARC_22 10 /* Direct 22 bit */
+#define R_SPARC_13 11 /* Direct 13 bit */
+#define R_SPARC_LO10 12 /* Truncated 10 bit */
+#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
+#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
+#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
+#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
+#define R_SPARC_COPY 19 /* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
+#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
+#define R_SPARC_RELATIVE 22 /* Adjust by program base */
+#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs. */
+
+#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10 30 /* Direct 10 bit */
+#define R_SPARC_11 31 /* Direct 11 bit */
+#define R_SPARC_64 32 /* Direct 64 bit */
+#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10 35 /* High middle 10 bits of ... */
+#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
+#define R_SPARC_7 43 /* Direct 7 bit */
+#define R_SPARC_5 44 /* Direct 5 bit */
+#define R_SPARC_6 45 /* Direct 6 bit */
+#define R_SPARC_DISP64 46 /* PC relative 64 bit */
+#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22 48 /* High 22 bit complemented */
+#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
+#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
+#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
+#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER 53 /* Global register usage */
+#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
+#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+/* Keep this the last entry. */
+#define R_SPARC_NUM 80
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM 2
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+
+#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */
+#define HWCAP_SPARC_STBAR 2
+#define HWCAP_SPARC_SWAP 4
+#define HWCAP_SPARC_MULDIV 8
+#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */
+#define HWCAP_SPARC_ULTRA3 32
+
+/* MIPS R3000 specific definitions. */
+
+/* Legal values for e_flags field of Elf32_Ehdr. */
+
+#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
+#define EF_MIPS_PIC 2 /* Contains PIC code */
+#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
+#define EF_MIPS_XGOT 8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2 32
+#define EF_MIPS_ABI_ON32 64
+#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
+
+/* Legal values for MIPS architecture level. */
+
+#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
+#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
+#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
+#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
+
+/* The following are non-official names and should not be used. */
+
+#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
+#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
+#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
+#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
+#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
+#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
+#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
+
+/* Special section indices. */
+
+#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
+#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
+#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
+#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
+#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
+#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
+#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
+#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
+#define SHT_MIPS_SHDR 0x70000010
+#define SHT_MIPS_FDESC 0x70000011
+#define SHT_MIPS_EXTSYM 0x70000012
+#define SHT_MIPS_DENSE 0x70000013
+#define SHT_MIPS_PDESC 0x70000014
+#define SHT_MIPS_LOCSYM 0x70000015
+#define SHT_MIPS_AUXSYM 0x70000016
+#define SHT_MIPS_OPTSYM 0x70000017
+#define SHT_MIPS_LOCSTR 0x70000018
+#define SHT_MIPS_LINE 0x70000019
+#define SHT_MIPS_RFDESC 0x7000001a
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
+#define SHF_MIPS_MERGE 0x20000000
+#define SHF_MIPS_ADDR 0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL 0x04000000
+#define SHF_MIPS_NAMES 0x02000000
+#define SHF_MIPS_NODUPE 0x01000000
+
+
+/* Symbol tables. */
+
+/* MIPS specific values for `st_other'. */
+#define STO_MIPS_DEFAULT 0x0
+#define STO_MIPS_INTERNAL 0x1
+#define STO_MIPS_HIDDEN 0x2
+#define STO_MIPS_PROTECTED 0x3
+#define STO_MIPS_SC_ALIGN_UNUSED 0xff
+
+/* MIPS specific values for `st_info'. */
+#define STB_MIPS_SPLIT_COMMON 13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB. */
+
+typedef union
+{
+ struct
+ {
+ Elf32_Word gt_current_g_value; /* -G value used for compilation */
+ Elf32_Word gt_unused; /* Not used */
+ } gt_header; /* First entry in section */
+ struct
+ {
+ Elf32_Word gt_g_value; /* If this value were used for -G */
+ Elf32_Word gt_bytes; /* This many bytes would be used */
+ } gt_entry; /* Subsequent entries in section */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO. */
+
+typedef struct
+{
+ Elf32_Word ri_gprmask; /* General registers used */
+ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
+ Elf32_Sword ri_gp_value; /* $gp register value */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS. */
+
+typedef struct
+{
+ unsigned char kind; /* Determines interpretation of the
+ variable part of descriptor. */
+ unsigned char size; /* Size of descriptor, including header. */
+ Elf32_Section section; /* Section header index of section affected,
+ 0 for global options. */
+ Elf32_Word info; /* Kind-specific information. */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options. */
+
+#define ODK_NULL 0 /* Undefined. */
+#define ODK_REGINFO 1 /* Register usage information. */
+#define ODK_EXCEPTIONS 2 /* Exception processing options. */
+#define ODK_PAD 3 /* Section padding options. */
+#define ODK_HWPATCH 4 /* Hardware workarounds performed */
+#define ODK_FILL 5 /* record the fill value used by the linker. */
+#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
+#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
+#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
+
+#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
+#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
+#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
+#define OEX_SMM 0x20000 /* Force sequential memory mode? */
+#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
+#define OEX_PRECISEFP OEX_FPDBUG
+#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
+
+#define OEX_FPU_INVAL 0x10
+#define OEX_FPU_DIV0 0x08
+#define OEX_FPU_OFLO 0x04
+#define OEX_FPU_UFLO 0x02
+#define OEX_FPU_INEX 0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
+
+#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
+#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
+#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
+#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
+
+#define OPAD_PREFIX 0x1
+#define OPAD_POSTFIX 0x2
+#define OPAD_SYMBOL 0x4
+
+/* Entry found in `.options' section. */
+
+typedef struct
+{
+ Elf32_Word hwp_flags1; /* Extra flags. */
+ Elf32_Word hwp_flags2; /* Extra flags. */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
+
+#define OHWA0_R4KEOP_CHECKED 0x00000001
+#define OHWA1_R4KEOP_CLEAN 0x00000002
+
+/* MIPS relocs. */
+
+#define R_MIPS_NONE 0 /* No reloc */
+#define R_MIPS_16 1 /* Direct 16 bit */
+#define R_MIPS_32 2 /* Direct 32 bit */
+#define R_MIPS_REL32 3 /* PC relative 32 bit */
+#define R_MIPS_26 4 /* Direct 26 bit shifted */
+#define R_MIPS_HI16 5 /* High 16 bit */
+#define R_MIPS_LO16 6 /* Low 16 bit */
+#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
+#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
+#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
+#define R_MIPS_PC16 10 /* PC relative 16 bit */
+#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_RELGOT 36
+#define R_MIPS_JALR 37
+/* Keep this the last entry. */
+#define R_MIPS_NUM 38
+
+/* Legal values for p_type field of Elf32_Phdr. */
+
+#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
+#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+
+/* Special program header types. */
+
+#define PF_MIPS_LOCAL 0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn. */
+
+#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
+#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
+#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS 0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
+#define DT_MIPS_MSYM 0x70000007
+#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
+#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
+#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
+#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in
+ DT_MIPS_DELTA_CLASS. */
+#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+ DT_MIPS_DELTA_INSTANCE. */
+#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+ DT_MIPS_DELTA_RELOC. */
+#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta
+ relocations refer to. */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+ DT_MIPS_DELTA_SYM. */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+ class declaration. */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+ DT_MIPS_DELTA_CLASSSYM. */
+#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
+#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+ function stored in GOT. */
+#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
+ by rld on dlopen() calls. */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
+#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
+#define DT_MIPS_NUM 0x32
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
+
+#define RHF_NONE 0 /* No flags */
+#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
+#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE (1 << 3)
+#define RHF_SGI_ONLY (1 << 4)
+#define RHF_GUARANTEE_INIT (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
+#define RHF_GUARANTEE_START_INIT (1 << 7)
+#define RHF_PIXIE (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
+#define RHF_REQUICKSTART (1 << 10)
+#define RHF_REQUICKSTARTED (1 << 11)
+#define RHF_CORD (1 << 12)
+#define RHF_NO_UNRES_UNDEF (1 << 13)
+#define RHF_RLD_ORDER_SAFE (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST. */
+
+typedef struct
+{
+ Elf32_Word l_name; /* Name (string table index) */
+ Elf32_Word l_time_stamp; /* Timestamp */
+ Elf32_Word l_checksum; /* Checksum */
+ Elf32_Word l_version; /* Interface version */
+ Elf32_Word l_flags; /* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+ Elf64_Word l_name; /* Name (string table index) */
+ Elf64_Word l_time_stamp; /* Timestamp */
+ Elf64_Word l_checksum; /* Checksum */
+ Elf64_Word l_version; /* Interface version */
+ Elf64_Word l_flags; /* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags. */
+
+#define LL_NONE 0
+#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
+#define LL_REQUIRE_MINOR (1 << 2)
+#define LL_EXPORTS (1 << 3)
+#define LL_DELAY_LOAD (1 << 4)
+#define LL_DELTA (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT. */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+/* HPPA specific definitions. */
+
+/* Legal values for e_flags field of Elf32_Ehdr. */
+
+#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */
+#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */
+#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch
+ prediction. */
+#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */
+#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are: */
+
+#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */
+#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */
+#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */
+
+/* Additional section indeces. */
+
+#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared
+ symbols in ANSI C. */
+#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */
+#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */
+#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
+
+#define STT_HP_OPAQUE (STT_LOOS + 0x1)
+#define STT_HP_STUB (STT_LOOS + 0x2)
+
+/* HPPA relocs. */
+
+#define R_PARISC_NONE 0 /* No reloc. */
+#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
+#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
+#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
+#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */
+#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */
+#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */
+#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */
+#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */
+#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */
+#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */
+#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */
+#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */
+#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */
+#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */
+#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */
+#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */
+#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */
+#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */
+#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */
+#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */
+#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */
+#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64 64 /* 64 bits function address. */
+#define R_PARISC_PLABEL32 65 /* 32 bits function address. */
+#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fct ptr. */
+#define R_PARISC_PLABEL14R 70 /* Left 21 bits of fct ptr. */
+#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */
+#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */
+#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */
+#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */
+#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */
+#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */
+#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */
+#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */
+#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */
+#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */
+#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */
+#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */
+#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */
+#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */
+#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */
+#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */
+#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */
+#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */
+#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */
+#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */
+#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */
+#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */
+#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */
+#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */
+#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */
+#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */
+#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */
+#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */
+#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */
+#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */
+#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */
+#define R_PARISC_LORESERVE 128
+#define R_PARISC_COPY 128 /* Copy relocation. */
+#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */
+#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */
+#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */
+#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */
+#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */
+#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */
+#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */
+#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */
+#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */
+#define R_PARISC_HIRESERVE 255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
+
+#define PT_HP_TLS (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
+#define PT_HP_STACK (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT 0x70000000
+#define PT_PARISC_UNWIND 0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */
+
+#define PF_PARISC_SBP 0x08000000
+
+#define PF_HP_PAGE_SIZE 0x00100000
+#define PF_HP_FAR_SHARED 0x00200000
+#define PF_HP_NEAR_SHARED 0x00400000
+#define PF_HP_CODE 0x01000000
+#define PF_HP_MODIFY 0x02000000
+#define PF_HP_LAZYSWAP 0x04000000
+#define PF_HP_SBP 0x08000000
+
+
+/* Alpha specific definitions. */
+
+/* Legal values for e_flags field of Elf64_Ehdr. */
+
+#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
+#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
+
+/* Legal values for sh_type field of Elf64_Shdr. */
+
+/* These two are primerily concerned with ECOFF debugging info. */
+#define SHT_ALPHA_DEBUG 0x70000001
+#define SHT_ALPHA_REGINFO 0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr. */
+
+#define SHF_ALPHA_GPREL 0x10000000
+
+/* Legal values for st_other field of Elf64_Sym. */
+#define STO_ALPHA_NOPV 0x80 /* No PV required. */
+#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
+
+/* Alpha relocs. */
+
+#define R_ALPHA_NONE 0 /* No reloc */
+#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
+#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
+#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
+#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
+#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
+#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
+#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */
+#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
+#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI 28
+#define R_ALPHA_TLSGD 29
+#define R_ALPHA_TLS_LDM 30
+#define R_ALPHA_DTPMOD64 31
+#define R_ALPHA_GOTDTPREL 32
+#define R_ALPHA_DTPREL64 33
+#define R_ALPHA_DTPRELHI 34
+#define R_ALPHA_DTPRELLO 35
+#define R_ALPHA_DTPREL16 36
+#define R_ALPHA_GOTTPREL 37
+#define R_ALPHA_TPREL64 38
+#define R_ALPHA_TPRELHI 39
+#define R_ALPHA_TPRELLO 40
+#define R_ALPHA_TPREL16 41
+/* Keep this the last entry. */
+#define R_ALPHA_NUM 46
+
+/* Magic values of the LITUSE relocation addend. */
+#define LITUSE_ALPHA_ADDR 0
+#define LITUSE_ALPHA_BASE 1
+#define LITUSE_ALPHA_BYTOFF 2
+#define LITUSE_ALPHA_JSR 3
+#define LITUSE_ALPHA_TLS_GD 4
+#define LITUSE_ALPHA_TLS_LDM 5
+
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags. */
+#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib
+ flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1 /* 32bit absolute address */
+#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+#define R_PPC_ADDR16 3 /* 16bit absolute address */
+#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10 /* PC relative 26 bit */
+#define R_PPC_REL14 11 /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* Keep this the last entry. */
+#define R_PPC_NUM 95
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+ in the SVR4 ELF ABI. */
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
+
+/* Diab tool relocations. */
+#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+ that may still be in object files. */
+#define R_PPC_TOC16 255
+
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */
+#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */
+#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
+#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */
+#define R_PPC64_ADDR64 38 /* doubleword64 S + A */
+#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */
+#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */
+#define R_PPC64_UADDR64 43 /* doubleword64 S + A */
+#define R_PPC64_REL64 44 /* doubleword64 S + A - P */
+#define R_PPC64_PLT64 45 /* doubleword64 L + A */
+#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */
+#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */
+#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */
+#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */
+#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */
+#define R_PPC64_TOC 51 /* doubleword64 .TOC */
+#define R_PPC64_PLTGOT16 52 /* half16* M + A */
+#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */
+#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */
+#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */
+
+#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */
+#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */
+#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */
+#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */
+#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */
+#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */
+#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */
+#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */
+#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */
+#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* Keep this the last entry. */
+#define R_PPC64_NUM 107
+
+/* PowerPC64 specific values for the Dyn d_tag field. */
+#define DT_PPC64_GLINK (DT_LOPROC + 0)
+#define DT_PPC64_OPD (DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_NUM 3
+
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_ARM_RELEXEC 0x01
+#define EF_ARM_HASENTRY 0x02
+#define EF_ARM_INTERWORK 0x04
+#define EF_ARM_APCS_26 0x08
+#define EF_ARM_APCS_FLOAT 0x10
+#define EF_ARM_PIC 0x20
+#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI 0x80
+#define EF_ARM_OLD_ABI 0x100
+
+/* Other constants defined in the ARM ELF spec. version B-01. */
+/* NB. These conflict with values defined above. */
+#define EF_ARM_SYMSARESORTED 0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_EABIMASK 0XFF000000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+
+/* Additional symbol types for Thumb */
+#define STT_ARM_TFUNC 0xd
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
+#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
+ in the input to a link step */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB 0x10000000 /* Segment contains the location
+ addressed by the static base */
+
+/* ARM relocs. */
+#define R_ARM_NONE 0 /* No reloc */
+#define R_ARM_PC24 1 /* PC relative 26 bit branch */
+#define R_ARM_ABS32 2 /* Direct 32 bit */
+#define R_ARM_REL32 3 /* PC relative 32 bit */
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5 /* Direct 16 bit */
+#define R_ARM_ABS12 6 /* Direct 12 bit */
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8 /* Direct 8 bit */
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+#define R_ARM_COPY 20 /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
+#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
+#define R_ARM_RELATIVE 23 /* Adjust by program base */
+#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
+#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32 26 /* 32 bit GOT entry */
+#define R_ARM_PLT32 27 /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0 32
+#define R_ARM_ALU_PCREL_15_8 33
+#define R_ARM_ALU_PCREL_23_15 34
+#define R_ARM_LDR_SBREL_11_0 35
+#define R_ARM_ALU_SBREL_19_12 36
+#define R_ARM_ALU_SBREL_27_20 37
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
+#define R_ARM_THM_PC9 103 /* thumb conditional branch */
+#define R_ARM_RXPC25 249
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS22 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+/* Keep this the last entry. */
+#define R_ARM_NUM 256
+
+/* IA-64 specific declarations. */
+
+/* Processor specific flags for the Ehdr e_flags field. */
+#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
+#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
+#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field. */
+#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
+#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
+#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
+
+/* Processor specific flags for the Phdr p_flags field. */
+#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field. */
+#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field. */
+#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
+#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field. */
+#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
+#define DT_IA_64_NUM 1
+
+/* IA-64 relocations. */
+#define R_IA64_NONE 0x00 /* none */
+#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
+#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
+#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
+#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
+#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
+#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
+#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY 0x84 /* copy relocation */
+#define R_IA64_SUB 0x85 /* Addend and symbol difference */
+#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
+#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
+#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* SH relocs. */
+#define R_SH_NONE 0
+#define R_SH_DIR32 1
+#define R_SH_REL32 2
+#define R_SH_DIR8WPN 3
+#define R_SH_IND12W 4
+#define R_SH_DIR8WPL 5
+#define R_SH_DIR8WPZ 6
+#define R_SH_DIR8BP 7
+#define R_SH_DIR8W 8
+#define R_SH_DIR8L 9
+#define R_SH_SWITCH16 25
+#define R_SH_SWITCH32 26
+#define R_SH_USES 27
+#define R_SH_COUNT 28
+#define R_SH_ALIGN 29
+#define R_SH_CODE 30
+#define R_SH_DATA 31
+#define R_SH_LABEL 32
+#define R_SH_SWITCH8 33
+#define R_SH_GNU_VTINHERIT 34
+#define R_SH_GNU_VTENTRY 35
+#define R_SH_TLS_GD_32 144
+#define R_SH_TLS_LD_32 145
+#define R_SH_TLS_LDO_32 146
+#define R_SH_TLS_IE_32 147
+#define R_SH_TLS_LE_32 148
+#define R_SH_TLS_DTPMOD32 149
+#define R_SH_TLS_DTPOFF32 150
+#define R_SH_TLS_TPOFF32 151
+#define R_SH_GOT32 160
+#define R_SH_PLT32 161
+#define R_SH_COPY 162
+#define R_SH_GLOB_DAT 163
+#define R_SH_JMP_SLOT 164
+#define R_SH_RELATIVE 165
+#define R_SH_GOTOFF 166
+#define R_SH_GOTPC 167
+/* Keep this the last entry. */
+#define R_SH_NUM 256
+
+/* Additional s390 relocs */
+
+#define R_390_NONE 0 /* No reloc. */
+#define R_390_8 1 /* Direct 8 bit. */
+#define R_390_12 2 /* Direct 12 bit. */
+#define R_390_16 3 /* Direct 16 bit. */
+#define R_390_32 4 /* Direct 32 bit. */
+#define R_390_PC32 5 /* PC relative 32 bit. */
+#define R_390_GOT12 6 /* 12 bit GOT offset. */
+#define R_390_GOT32 7 /* 32 bit GOT offset. */
+#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
+#define R_390_COPY 9 /* Copy symbol at runtime. */
+#define R_390_GLOB_DAT 10 /* Create GOT entry. */
+#define R_390_JMP_SLOT 11 /* Create PLT entry. */
+#define R_390_RELATIVE 12 /* Adjust by program base. */
+#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */
+#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
+#define R_390_GOT16 15 /* 16 bit GOT offset. */
+#define R_390_PC16 16 /* PC relative 16 bit. */
+#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
+#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
+#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
+#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
+#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
+#define R_390_64 22 /* Direct 64 bit. */
+#define R_390_PC64 23 /* PC relative 64 bit. */
+#define R_390_GOT64 24 /* 64 bit GOT offset. */
+#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
+#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
+#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
+#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
+#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
+#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
+#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
+#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
+#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
+#define R_390_TLS_GDCALL 38 /* Tag for function call in general
+ dynamic TLS code. */
+#define R_390_TLS_LDCALL 39 /* Tag for function call in local
+ dynamic TLS code. */
+#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic
+ thread local data. */
+#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic
+ thread local data. */
+#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic
+ thread local data in LE code. */
+#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic
+ thread local data in LE code. */
+#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to
+ static TLS block. */
+#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to
+ static TLS block. */
+#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS
+ block. */
+#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS
+ block. */
+#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
+#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
+#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS
+ block. */
+#define R_390_20 57 /* Direct 20 bit. */
+#define R_390_GOT20 58 /* 20 bit GOT offset. */
+#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */
+#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS
+ block offset. */
+/* Keep this the last entry. */
+#define R_390_NUM 61
+
+
+/* CRIS relocations. */
+#define R_CRIS_NONE 0
+#define R_CRIS_8 1
+#define R_CRIS_16 2
+#define R_CRIS_32 3
+#define R_CRIS_8_PCREL 4
+#define R_CRIS_16_PCREL 5
+#define R_CRIS_32_PCREL 6
+#define R_CRIS_GNU_VTINHERIT 7
+#define R_CRIS_GNU_VTENTRY 8
+#define R_CRIS_COPY 9
+#define R_CRIS_GLOB_DAT 10
+#define R_CRIS_JUMP_SLOT 11
+#define R_CRIS_RELATIVE 12
+#define R_CRIS_16_GOT 13
+#define R_CRIS_32_GOT 14
+#define R_CRIS_16_GOTPLT 15
+#define R_CRIS_32_GOTPLT 16
+#define R_CRIS_32_GOTREL 17
+#define R_CRIS_32_PLT_GOTREL 18
+#define R_CRIS_32_PLT_PCREL 19
+
+#define R_CRIS_NUM 20
+
+
+/* AMD x86-64 relocations. */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
+ offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
+#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset
+ to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset
+ to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset
+ to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
+
+#define R_X86_64_NUM 24
+
+
+/* AM33 relocations. */
+#define R_MN10300_NONE 0 /* No reloc. */
+#define R_MN10300_32 1 /* Direct 32 bit. */
+#define R_MN10300_16 2 /* Direct 16 bit. */
+#define R_MN10300_8 3 /* Direct 8 bit. */
+#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */
+#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */
+#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
+#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */
+#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */
+#define R_MN10300_24 9 /* Direct 24 bit. */
+#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */
+#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */
+#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */
+#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */
+#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */
+#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */
+#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */
+#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */
+#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */
+#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */
+#define R_MN10300_COPY 20 /* Copy symbol at runtime. */
+#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */
+#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */
+#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
+
+#define R_MN10300_NUM 24
+
+
+/* M32R relocs. */
+#define R_M32R_NONE 0 /* No reloc. */
+#define R_M32R_16 1 /* Direct 16 bit. */
+#define R_M32R_32 2 /* Direct 32 bit. */
+#define R_M32R_24 3 /* Direct 24 bit. */
+#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */
+#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */
+#define R_M32R_LO16 9 /* Low 16 bit. */
+#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */
+#define R_M32R_GNU_VTINHERIT 11
+#define R_M32R_GNU_VTENTRY 12
+/* M32R relocs use SHT_RELA. */
+#define R_M32R_16_RELA 33 /* Direct 16 bit. */
+#define R_M32R_32_RELA 34 /* Direct 32 bit. */
+#define R_M32R_24_RELA 35 /* Direct 24 bit. */
+#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */
+#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */
+#define R_M32R_LO16_RELA 41 /* Low 16 bit */
+#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */
+#define R_M32R_RELA_GNU_VTINHERIT 43
+#define R_M32R_RELA_GNU_VTENTRY 44
+#define R_M32R_REL32 45 /* PC relative 32 bit */
+
+#define R_M32R_GOT24 48 /* 24 bit GOT entry */
+#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */
+#define R_M32R_COPY 50 /* Copy symbol at runtime */
+#define R_M32R_GLOB_DAT 51 /* Create GOT entry */
+#define R_M32R_JMP_SLOT 52 /* Create PLT entry */
+#define R_M32R_RELATIVE 53 /* Adjust by program base */
+#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */
+#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */
+#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned
+ low */
+#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed
+ low */
+#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */
+#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to
+ GOT with unsigned low */
+#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to
+ GOT with signed low */
+#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to
+ GOT */
+#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT
+ with unsigned low */
+#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT
+ with signed low */
+#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */
+#define R_M32R_NUM 256 /* Keep this the last entry. */
+
+
+__END_DECLS
+
+#endif /* elf.h */
diff --git a/tools/mklibs/patches/001-compile.patch b/tools/mklibs/patches/001-compile.patch
new file mode 100644
index 0000000..09b831a
--- /dev/null
+++ b/tools/mklibs/patches/001-compile.patch
@@ -0,0 +1,8 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,4 +1,4 @@
+-AC_INIT([mklibs],m4_esyscmd(dpkg-parsechangelog | perl -ne 'print $1 if m/^Version: (.*)$/;'))
++AC_INIT([mklibs],m4_esyscmd([head -n1 debian/changelog | awk -F'[\\\\(\\\\)]' '{ print $2 }' | xargs -I{} echo -n {}]))
+ AM_INIT_AUTOMAKE([foreign no-define])
+ AC_CONFIG_HEADERS([config.h])
+ AM_MAINTAINER_MODE
diff --git a/tools/mklibs/patches/002-disable_symbol_checks.patch b/tools/mklibs/patches/002-disable_symbol_checks.patch
new file mode 100644
index 0000000..44be637
--- /dev/null
+++ b/tools/mklibs/patches/002-disable_symbol_checks.patch
@@ -0,0 +1,20 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -524,7 +524,7 @@ while 1:
+ # No progress in last pass. Verify all remaining symbols are weak.
+ for name in unresolved:
+ if not needed_symbols[name].weak:
+- raise Exception("Unresolvable symbol %s" % name)
++ print "WARNING: Unresolvable symbol %s" % name
+ break
+
+ previous_pass_unresolved = unresolved
+@@ -559,7 +559,7 @@ while 1:
+ for name in needed_symbols:
+ if not name in symbol_provider:
+ if not needed_symbols[name].weak:
+- raise Exception("No library provides non-weak %s" % name)
++ print "WARNING: Unresolvable symbol %s" % name
+ else:
+ lib = symbol_provider[name]
+ library_symbols_used[lib].add(library_symbols[lib][name])
diff --git a/tools/mklibs/patches/003-no_copy.patch b/tools/mklibs/patches/003-no_copy.patch
new file mode 100644
index 0000000..e0ab2ac
--- /dev/null
+++ b/tools/mklibs/patches/003-no_copy.patch
@@ -0,0 +1,50 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -463,7 +463,7 @@ while 1:
+ passnr = passnr + 1
+ # Gather all already reduced libraries and treat them as objects as well
+ small_libs = []
+- for lib in regexpfilter(os.listdir(dest_path), "(.*-so-stripped)$"):
++ for lib in regexpfilter(os.listdir(dest_path), "(.*-so)$"):
+ obj = dest_path + "/" + lib
+ small_libs.append(obj)
+ inode = os.stat(obj)[ST_INO]
+@@ -579,12 +579,7 @@ while 1:
+ if not so_file:
+ sys.exit("File not found:" + library)
+ pic_file = find_pic(library)
+- if not pic_file:
+- # No pic file, so we have to use the .so file, no reduction
+- debug(DEBUG_VERBOSE, "No pic file found for", so_file, "; copying")
+- command(target + "objcopy", "--strip-unneeded -R .note -R .comment",
+- so_file, dest_path + "/" + so_file_name + "-so-stripped")
+- else:
++ if pic_file:
+ # we have a pic file, recompile
+ debug(DEBUG_SPAM, "extracting from:", pic_file, "so_file:", so_file)
+ soname = extract_soname(so_file)
+@@ -627,22 +622,14 @@ while 1:
+ cmd.append(library_depends_gcc_libnames(so_file))
+ command(target + "gcc", *cmd)
+
+- # strip result
+- command(target + "objcopy", "--strip-unneeded -R .note -R .comment",
+- dest_path + "/" + so_file_name + "-so",
+- dest_path + "/" + so_file_name + "-so-stripped")
+ ## DEBUG
+ debug(DEBUG_VERBOSE, so_file, "\t", `os.stat(so_file)[ST_SIZE]`)
+ debug(DEBUG_VERBOSE, dest_path + "/" + so_file_name + "-so", "\t",
+ `os.stat(dest_path + "/" + so_file_name + "-so")[ST_SIZE]`)
+- debug(DEBUG_VERBOSE, dest_path + "/" + so_file_name + "-so-stripped",
+- "\t", `os.stat(dest_path + "/" + so_file_name + "-so-stripped")[ST_SIZE]`)
+
+ # Finalising libs and cleaning up
+-for lib in regexpfilter(os.listdir(dest_path), "(.*)-so-stripped$"):
+- os.rename(dest_path + "/" + lib + "-so-stripped", dest_path + "/" + lib)
+-for lib in regexpfilter(os.listdir(dest_path), "(.*-so)$"):
+- os.remove(dest_path + "/" + lib)
++for lib in regexpfilter(os.listdir(dest_path), "(.*)-so$"):
++ os.rename(dest_path + "/" + lib + "-so", dest_path + "/" + lib)
+
+ # Canonicalize library names.
+ for lib in regexpfilter(os.listdir(dest_path), "(.*so[.\d]*)$"):
diff --git a/tools/mklibs/patches/004-libpthread_link.patch b/tools/mklibs/patches/004-libpthread_link.patch
new file mode 100644
index 0000000..657e232
--- /dev/null
+++ b/tools/mklibs/patches/004-libpthread_link.patch
@@ -0,0 +1,28 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -106,14 +106,14 @@ def library_depends(obj):
+
+ # Return a list of libraries the passed objects depend on. The
+ # libraries are in "-lfoo" format suitable for passing to gcc.
+-def library_depends_gcc_libnames(obj):
++def library_depends_gcc_libnames(obj, soname):
+ if not os.access(obj, os.F_OK):
+ raise Exception("Cannot find lib: " + obj)
+ libs = library_depends(obj)
+ ret = []
+ for i in libs:
+ match = re.match("^(((?P<ld>ld\S*)|(lib(?P<lib>\S+))))\.so.*$", i)
+- if match:
++ if match and not soname in ("libpthread.so.0"):
+ if match.group('ld'):
+ ret.append(find_lib(match.group(0)))
+ elif match.group('lib'):
+@@ -619,7 +619,7 @@ while 1:
+ cmd.extend(extra_flags)
+ cmd.append("-lgcc")
+ cmd.extend(["-L%s" % a for a in [dest_path] + [sysroot + b for b in lib_path if sysroot == "" or b not in ("/" + libdir + "/", "/usr/" + libdir + "/")]])
+- cmd.append(library_depends_gcc_libnames(so_file))
++ cmd.append(library_depends_gcc_libnames(so_file, soname))
+ command(target + "gcc", *cmd)
+
+ ## DEBUG
diff --git a/tools/mklibs/patches/005-duplicate_syms.patch b/tools/mklibs/patches/005-duplicate_syms.patch
new file mode 100644
index 0000000..8428abf
--- /dev/null
+++ b/tools/mklibs/patches/005-duplicate_syms.patch
@@ -0,0 +1,35 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -531,7 +531,6 @@ while 1:
+
+ library_symbols = {}
+ library_symbols_used = {}
+- symbol_provider = {}
+
+ # WORKAROUND: Always add libgcc on old-abi arm
+ header = elf_header(find_lib(libraries.copy().pop()))
+@@ -549,20 +548,13 @@ while 1:
+ library_symbols_used[library] = set()
+ for symbol in symbols:
+ for name in symbol.base_names():
+- if name in symbol_provider:
+- debug(DEBUG_SPAM, "duplicate symbol %s in %s and %s" % (symbol, symbol_provider[name], library))
+- else:
+- library_symbols[library][name] = symbol
+- symbol_provider[name] = library
++ library_symbols[library][name] = symbol
+
+ # which symbols are actually used from each lib
+ for name in needed_symbols:
+- if not name in symbol_provider:
+- if not needed_symbols[name].weak:
+- print "WARNING: Unresolvable symbol %s" % name
+- else:
+- lib = symbol_provider[name]
+- library_symbols_used[lib].add(library_symbols[lib][name])
++ for lib in libraries:
++ if name in library_symbols[lib]:
++ library_symbols_used[lib].add(library_symbols[lib][name])
+
+ # reduce libraries
+ for library in libraries:
diff --git a/tools/mklibs/patches/006-uclibc_init.patch b/tools/mklibs/patches/006-uclibc_init.patch
new file mode 100644
index 0000000..2df7fe4
--- /dev/null
+++ b/tools/mklibs/patches/006-uclibc_init.patch
@@ -0,0 +1,14 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -595,6 +595,11 @@ while 1:
+ extra_post_obj.append(sysroot + libc_extras_dir + "/sofini.o")
+ symbols.add(ProvidedSymbol('__dso_handle', None, None, True))
+
++ if soname in ("libc.so.0"):
++ symbols.add(ProvidedSymbol('__uClibc_init', None, None, True))
++ symbols.add(ProvidedSymbol('__uClibc_fini', None, None, True))
++ extra_flags.append("-Wl,-init,__uClibc_init")
++
+ map_file = find_pic_map(library)
+ if map_file:
+ extra_flags.append("-Wl,--version-script=" + map_file)
diff --git a/tools/mklibs/patches/007-gc_sections.patch b/tools/mklibs/patches/007-gc_sections.patch
new file mode 100644
index 0000000..068d88a
--- /dev/null
+++ b/tools/mklibs/patches/007-gc_sections.patch
@@ -0,0 +1,11 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -607,7 +607,7 @@ while 1:
+ # compile in only used symbols
+ cmd = []
+ cmd.extend(gcc_options)
+- cmd.append("-nostdlib -nostartfiles -shared -Wl,-soname=" + soname)
++ cmd.append("-nostdlib -nostartfiles -shared -Wl,--gc-sections -Wl,-soname=" + soname)
+ cmd.extend(["-u%s" % a.linker_name() for a in symbols])
+ cmd.extend(["-o", dest_path + "/" + so_file_name + "-so"])
+ cmd.extend(extra_pre_obj)
diff --git a/tools/mklibs/patches/008-uclibc_libgcc_link.patch b/tools/mklibs/patches/008-uclibc_libgcc_link.patch
new file mode 100644
index 0000000..432a313
--- /dev/null
+++ b/tools/mklibs/patches/008-uclibc_libgcc_link.patch
@@ -0,0 +1,37 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -113,11 +113,8 @@ def library_depends_gcc_libnames(obj, so
+ ret = []
+ for i in libs:
+ match = re.match("^(((?P<ld>ld\S*)|(lib(?P<lib>\S+))))\.so.*$", i)
+- if match and not soname in ("libpthread.so.0"):
+- if match.group('ld'):
+- ret.append(find_lib(match.group(0)))
+- elif match.group('lib'):
+- ret.append('-l%s' % match.group('lib'))
++ if match:
++ ret.append(find_lib(match.group(0)))
+ return ' '.join(ret)
+
+ class Symbol(object):
+@@ -584,6 +581,7 @@ while 1:
+ extra_flags = []
+ extra_pre_obj = []
+ extra_post_obj = []
++ libgcc_link = find_lib("libgcc_s.so.1")
+
+ symbols.update(library_symbols_used[library])
+
+@@ -614,9 +612,10 @@ while 1:
+ cmd.append(pic_file)
+ cmd.extend(extra_post_obj)
+ cmd.extend(extra_flags)
+- cmd.append("-lgcc")
+ cmd.extend(["-L%s" % a for a in [dest_path] + [sysroot + b for b in lib_path if sysroot == "" or b not in ("/" + libdir + "/", "/usr/" + libdir + "/")]])
+- cmd.append(library_depends_gcc_libnames(so_file, soname))
++ if soname != "libgcc_s.so.1":
++ cmd.append(library_depends_gcc_libnames(so_file, soname))
++ cmd.append(libgcc_link)
+ command(target + "gcc", *cmd)
+
+ ## DEBUG
diff --git a/tools/mklibs/patches/009-uclibc_libpthread_symbols.patch b/tools/mklibs/patches/009-uclibc_libpthread_symbols.patch
new file mode 100644
index 0000000..34866f7
--- /dev/null
+++ b/tools/mklibs/patches/009-uclibc_libpthread_symbols.patch
@@ -0,0 +1,63 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -162,9 +162,10 @@ def undefined_symbols(obj):
+ return result
+
+ class ProvidedSymbol(Symbol):
+- def __init__(self, name, version, library, default_version):
++ def __init__(self, name, version, library, default_version, weak):
+ super(ProvidedSymbol, self).__init__(name, version, library)
+ self.default_version = default_version
++ self.weak = weak
+
+ def base_names(self):
+ ret = []
+@@ -205,11 +206,15 @@ def provided_symbols(obj):
+ if version_string.lower() not in ('base', 'none'):
+ version = version_string
+
++ weak = False
++ if weak_string.lower() == 'true':
++ weak = True
++
+ default_version = False
+ if default_version_string.lower() == 'true':
+ default_version = True
+
+- result.append(ProvidedSymbol(name, version, library, default_version))
++ result.append(ProvidedSymbol(name, version, library, default_version, weak))
+
+ return result
+
+@@ -500,6 +505,9 @@ while 1:
+ debug(DEBUG_SPAM, "present_symbols adding %s" % symbol)
+ names = symbol.base_names()
+ for name in names:
++ if name in present_symbols:
++ if symbol.library != present_symbols[name].library:
++ needed_symbols[name] = UndefinedSymbol(name, True, symbol.version, symbol.library)
+ present_symbols[name] = symbol
+
+ # are we finished?
+@@ -591,12 +599,16 @@ while 1:
+ # may segfault in ptmalloc_init due to undefined weak reference
+ extra_pre_obj.append(sysroot + libc_extras_dir + "/soinit.o")
+ extra_post_obj.append(sysroot + libc_extras_dir + "/sofini.o")
+- symbols.add(ProvidedSymbol('__dso_handle', None, None, True))
++ symbols.add(ProvidedSymbol('__dso_handle', None, None, True, True))
+
+- if soname in ("libc.so.0"):
+- symbols.add(ProvidedSymbol('__uClibc_init', None, None, True))
+- symbols.add(ProvidedSymbol('__uClibc_fini', None, None, True))
+- extra_flags.append("-Wl,-init,__uClibc_init")
++ if soname == "libc.so.0":
++ symbols.add(ProvidedSymbol('__uClibc_init', None, None, True, True))
++ symbols.add(ProvidedSymbol('__uClibc_fini', None, None, True, True))
++ extra_pre_obj.append("-Wl,-init,__uClibc_init")
++
++ if soname == "libpthread.so.0":
++ symbols.add(ProvidedSymbol('__pthread_initialize_minimal_internal', None, None, True, True))
++ extra_flags.append("-Wl,-z,nodelete,-z,initfirst,-init=__pthread_initialize_minimal_internal")
+
+ map_file = find_pic_map(library)
+ if map_file:
diff --git a/tools/mklibs/patches/010-remove_STT_GNU_IFUNC.patch b/tools/mklibs/patches/010-remove_STT_GNU_IFUNC.patch
new file mode 100644
index 0000000..6bae8c7
--- /dev/null
+++ b/tools/mklibs/patches/010-remove_STT_GNU_IFUNC.patch
@@ -0,0 +1,20 @@
+--- a/src/mklibs-readelf/main.cpp
++++ b/src/mklibs-readelf/main.cpp
+@@ -84,7 +84,7 @@ static void process_symbols_provided (co
+ continue;
+ if (shndx == SHN_UNDEF || shndx == SHN_ABS)
+ continue;
+- if (type != STT_NOTYPE && type != STT_OBJECT && type != STT_FUNC && type != STT_GNU_IFUNC && type != STT_COMMON && type != STT_TLS)
++ if (type != STT_NOTYPE && type != STT_OBJECT && type != STT_FUNC && type != STT_COMMON && type != STT_TLS)
+ continue;
+ if (!name.size())
+ continue;
+@@ -115,7 +115,7 @@ static void process_symbols_undefined (c
+ continue;
+ if (shndx != SHN_UNDEF)
+ continue;
+- if (type != STT_NOTYPE && type != STT_OBJECT && type != STT_FUNC && type != STT_GNU_IFUNC && type != STT_COMMON && type != STT_TLS)
++ if (type != STT_NOTYPE && type != STT_OBJECT && type != STT_FUNC && type != STT_COMMON && type != STT_TLS)
+ continue;
+ if (!name.size())
+ continue;
diff --git a/tools/mklibs/patches/011-remove_multiarch.patch b/tools/mklibs/patches/011-remove_multiarch.patch
new file mode 100644
index 0000000..a32d8ee
--- /dev/null
+++ b/tools/mklibs/patches/011-remove_multiarch.patch
@@ -0,0 +1,10 @@
+--- a/src/mklibs
++++ b/src/mklibs
+@@ -263,6 +263,7 @@ def extract_soname(so_file):
+ return ""
+
+ def multiarch(paths):
++ return paths
+ devnull = open('/dev/null', 'w')
+ dpkg_architecture = subprocess.Popen(
+ ['dpkg-architecture', '-qDEB_HOST_MULTIARCH'],
diff --git a/tools/mm-macros/Makefile b/tools/mm-macros/Makefile
new file mode 100644
index 0000000..94ce0de
--- /dev/null
+++ b/tools/mm-macros/Makefile
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2010-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mm-macros
+PKG_VERSION:=0.9.7
+
+PKG_SOURCE_URL:=http://ftp.gnome.org/pub/GNOME/sources/mm-common/0.9
+PKG_SOURCE:=mm-common-$(PKG_VERSION).tar.xz
+PKG_MD5SUM:=a8b7c11db81a72168bf38d88d97df686
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/mm-common-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/share/aclocal
+ $(INSTALL_DATA) $(HOST_BUILD_DIR)/macros/*.m4 $(STAGING_DIR_HOST)/share/aclocal/
+endef
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/mpc/Makefile b/tools/mpc/Makefile
new file mode 100644
index 0000000..f0bf8f4
--- /dev/null
+++ b/tools/mpc/Makefile
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2009-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mpc
+PKG_VERSION:=1.0.3
+
+PKG_SOURCE_URL:=@GNU/mpc/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_MD5SUM:=d6a1d5f8ddea3abd2cc3e98f58352d26
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport CFLAGS
+
+HOST_CONFIGURE_ARGS += \
+ --enable-static \
+ --disable-shared \
+ --with-mpfr=$(TOPDIR)/staging_dir/host \
+ --with-gmp=$(TOPDIR)/staging_dir/host
+
+$(eval $(call HostBuild))
diff --git a/tools/mpfr/Makefile b/tools/mpfr/Makefile
new file mode 100644
index 0000000..16624a7
--- /dev/null
+++ b/tools/mpfr/Makefile
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2009-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mpfr
+PKG_VERSION:=3.1.3
+
+PKG_SOURCE_URL:=http://www.mpfr.org/mpfr-$(PKG_VERSION) \
+ @GNU/mpfr
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_MD5SUM:=5fdfa3cfa5c86514ee4a241a1affa138
+
+HOST_BUILD_PARALLEL:=1
+HOST_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += \
+ --enable-static \
+ --disable-shared \
+ --with-gmp=$(STAGING_DIR_HOST)
+
+$(eval $(call HostBuild))
diff --git a/tools/mpfr/patches/001-only_src.patch b/tools/mpfr/patches/001-only_src.patch
new file mode 100644
index 0000000..4a07cb9
--- /dev/null
+++ b/tools/mpfr/patches/001-only_src.patch
@@ -0,0 +1,22 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -18,7 +18,7 @@
+ # old Automake version.
+ ACLOCAL_AMFLAGS = -I m4
+
+-SUBDIRS = doc src tests tune
++SUBDIRS = src
+
+ nobase_dist_doc_DATA = AUTHORS BUGS COPYING COPYING.LESSER NEWS TODO \
+ examples/ReadMe examples/divworst.c examples/rndo-add.c examples/sample.c \
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -377,7 +377,7 @@ top_builddir = @top_builddir@
+ # libtoolize and in case some developer needs to switch back to an
+ # old Automake version.
+ ACLOCAL_AMFLAGS = -I m4
+-SUBDIRS = doc src tests tune
++SUBDIRS = src
+ nobase_dist_doc_DATA = AUTHORS BUGS COPYING COPYING.LESSER NEWS TODO \
+ examples/ReadMe examples/divworst.c examples/rndo-add.c examples/sample.c \
+ examples/version.c
diff --git a/tools/mpfr/patches/100-freebsd-compat.patch b/tools/mpfr/patches/100-freebsd-compat.patch
new file mode 100644
index 0000000..fa28a67
--- /dev/null
+++ b/tools/mpfr/patches/100-freebsd-compat.patch
@@ -0,0 +1,10 @@
+--- a/src/vasprintf.c
++++ b/src/vasprintf.c
+@@ -42,6 +42,7 @@ http://www.gnu.org/licenses/ or write to
+ #endif /* HAVE_VA_COPY */
+
+ #ifdef HAVE_WCHAR_H
++#include <stddef.h>
+ #include <wchar.h>
+ #endif
+
diff --git a/tools/mtd-utils/Makefile b/tools/mtd-utils/Makefile
new file mode 100644
index 0000000..b863179
--- /dev/null
+++ b/tools/mtd-utils/Makefile
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtd-utils
+PKG_VERSION:=1.5.1
+
+PKG_SOURCE_VERSION:=92686f212c9a4e16891c6a3c57629cbf4f0f8360
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+PKG_SOURCE_URL:=git://git.infradead.org/mtd-utils.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_MIRROR_MD5SUM:=9fe0518213feddacd1842935dddeb6c8
+PKG_CAT:=zcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CFLAGS += -I$(STAGING_DIR_HOST)/include/e2fsprogs
+CFLAGS := $(HOST_CFLAGS) -I$(HOST_BUILD_DIR)/include -L$(HOST_BUILD_DIR) -L$(STAGING_DIR_HOST)/lib -DNO_NATIVE_SUPPORT
+ifneq ($(HOST_OS),Linux)
+CFLAGS += -Dloff_t=off_t -D__BYTE_ORDER=BYTE_ORDER -include getline.h -include endian.h -I$(CURDIR)/include -include fls.h
+MTD_STATIC := 0
+else
+MTD_STATIC := 1
+endif
+
+MTD_MAKEOPTS = \
+ CFLAGS="$(CFLAGS)" \
+ LDFLAGS="$(HOST_LDFLAGS)" \
+ WITHOUT_LZO=1 WITHOUT_XATTR=1 \
+ SUBDIRS="" \
+ BUILDDIR="$(HOST_BUILD_DIR)" \
+ STATIC=$(MTD_STATIC) \
+ V=$(if $(findstring c,$(OPENWRT_VERBOSE)),1)
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) \
+ $(MTD_MAKEOPTS) \
+ TARGETS="mkfs.jffs2 ubi-utils/ubinize mkfs.ubifs/mkfs.ubifs"
+endef
+
+define Host/Install
+ $(CP) \
+ $(HOST_BUILD_DIR)/mkfs.jffs2 \
+ $(HOST_BUILD_DIR)/mkfs.ubifs/mkfs.ubifs \
+ $(HOST_BUILD_DIR)/ubi-utils/ubinize \
+ $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/{mkfs.jffs2,mkfs.ubifs,ubinize}
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/mtd-utils/include/fls.h b/tools/mtd-utils/include/fls.h
new file mode 100644
index 0000000..7514253
--- /dev/null
+++ b/tools/mtd-utils/include/fls.h
@@ -0,0 +1,2 @@
+#include <string.h>
+#define fls local_fls
diff --git a/tools/mtd-utils/include/linux/types.h b/tools/mtd-utils/include/linux/types.h
new file mode 100644
index 0000000..559fac7
--- /dev/null
+++ b/tools/mtd-utils/include/linux/types.h
@@ -0,0 +1,18 @@
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#include <mtd/ubi-media.h>
+
+typedef uint16_t __u16;
+typedef uint32_t __u32;
+typedef uint64_t __u64;
+
+typedef __u16 __le16;
+typedef __u32 __le32;
+typedef __u64 __le64;
+typedef __u64 off64_t;
+
+typedef __u16 __sum16;
+typedef __u32 __wsum;
+
+#endif /* _LINUX_TYPES_H */
diff --git a/tools/mtd-utils/patches/100-sscanf_fix.patch b/tools/mtd-utils/patches/100-sscanf_fix.patch
new file mode 100644
index 0000000..0af583f
--- /dev/null
+++ b/tools/mtd-utils/patches/100-sscanf_fix.patch
@@ -0,0 +1,11 @@
+--- a/mkfs.jffs2.c
++++ b/mkfs.jffs2.c
+@@ -422,7 +422,7 @@ static int interpret_table_entry(struct
+
+ if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu",
+ SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor,
+- &start, &increment, &count) < 0)
++ &start, &increment, &count) < 10)
+ {
+ return 1;
+ }
diff --git a/tools/mtd-utils/patches/110-portability.patch b/tools/mtd-utils/patches/110-portability.patch
new file mode 100644
index 0000000..4ad209a
--- /dev/null
+++ b/tools/mtd-utils/patches/110-portability.patch
@@ -0,0 +1,191 @@
+--- a/compr_lzo.c
++++ b/compr_lzo.c
+@@ -26,7 +26,6 @@
+ #include <string.h>
+
+ #ifndef WITHOUT_LZO
+-#include <asm/types.h>
+ #include <linux/jffs2.h>
+ #include <lzo/lzo1x.h>
+ #include "compr.h"
+--- a/compr_zlib.c
++++ b/compr_zlib.c
+@@ -39,7 +39,6 @@
+ #include <zlib.h>
+ #undef crc32
+ #include <stdio.h>
+-#include <asm/types.h>
+ #include <linux/jffs2.h>
+ #include "common.h"
+ #include "compr.h"
+--- a/rbtree.h
++++ b/rbtree.h
+@@ -94,8 +94,7 @@ static inline struct page * rb_insert_pa
+ #ifndef _LINUX_RBTREE_H
+ #define _LINUX_RBTREE_H
+
+-#include <linux/kernel.h>
+-#include <linux/stddef.h>
++#include <stddef.h>
+
+ struct rb_node
+ {
+--- a/include/mtd/ubi-media.h
++++ b/include/mtd/ubi-media.h
+@@ -30,7 +30,15 @@
+ #ifndef __UBI_MEDIA_H__
+ #define __UBI_MEDIA_H__
+
++#ifdef __linux__
+ #include <asm/byteorder.h>
++#else
++#include <stdint.h>
++typedef uint8_t __u8;
++typedef uint16_t __be16;
++typedef uint32_t __be32;
++typedef uint64_t __be64;
++#endif
+
+ /* The version of UBI images supported by this implementation */
+ #define UBI_VERSION 1
+--- a/mkfs.ubifs/mkfs.ubifs.h
++++ b/mkfs.ubifs/mkfs.ubifs.h
+@@ -32,7 +32,17 @@
+ #include <endian.h>
+ #include <byteswap.h>
+ #include <linux/types.h>
++#ifdef __linux__
+ #include <linux/fs.h>
++# if defined(__x86_64__) && defined(__ILP32__)
++# define llseek lseek64
++# endif
++#else
++# ifndef O_LARGEFILE
++# define O_LARGEFILE 0
++# endif
++# define llseek lseek
++#endif
+
+ #include <getopt.h>
+ #include <sys/types.h>
+--- a/mkfs.ubifs/mkfs.ubifs.c
++++ b/mkfs.ubifs/mkfs.ubifs.c
+@@ -1010,6 +1010,7 @@ static int add_inode_with_data(struct st
+
+ if (c->default_compr != UBIFS_COMPR_NONE)
+ use_flags |= UBIFS_COMPR_FL;
++#ifndef NO_NATIVE_SUPPORT
+ if (flags & FS_COMPR_FL)
+ use_flags |= UBIFS_COMPR_FL;
+ if (flags & FS_SYNC_FL)
+@@ -1020,6 +1021,7 @@ static int add_inode_with_data(struct st
+ use_flags |= UBIFS_APPEND_FL;
+ if (flags & FS_DIRSYNC_FL && S_ISDIR(st->st_mode))
+ use_flags |= UBIFS_DIRSYNC_FL;
++#endif
+
+ memset(ino, 0, UBIFS_INO_NODE_SZ);
+
+@@ -1089,7 +1091,9 @@ static int add_dir_inode(DIR *dir, ino_t
+ fd = dirfd(dir);
+ if (fd == -1)
+ return sys_err_msg("dirfd failed");
++#ifndef NO_NATIVE_SUPPORT
+ if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1)
++#endif
+ flags = 0;
+ }
+
+@@ -1274,10 +1278,12 @@ static int add_file(const char *path_nam
+ key_write(&key, &dn->key);
+ dn->size = cpu_to_le32(bytes_read);
+ out_len = NODE_BUFFER_SIZE - UBIFS_DATA_NODE_SZ;
++#ifndef NO_NATIVE_SUPPORT
+ if (c->default_compr == UBIFS_COMPR_NONE &&
+ (flags & FS_COMPR_FL))
+ use_compr = UBIFS_COMPR_LZO;
+ else
++#endif
+ use_compr = c->default_compr;
+ compr_type = compress_data(buf, bytes_read, &dn->data,
+ &out_len, use_compr);
+@@ -1319,7 +1325,9 @@ static int add_non_dir(const char *path_
+ if (fd == -1)
+ return sys_err_msg("failed to open file '%s'",
+ path_name);
++#ifndef NO_NATIVE_SUPPORT
+ if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1)
++#endif
+ flags = 0;
+ if (close(fd) == -1)
+ return sys_err_msg("failed to close file '%s'",
+--- a/mkfs.ubifs/devtable.c
++++ b/mkfs.ubifs/devtable.c
+@@ -134,6 +134,7 @@ static int interpret_table_entry(const c
+ unsigned int mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
+ unsigned int start = 0, increment = 0, count = 0;
+
++ buf[1023] = 0;
+ if (sscanf(line, "%1023s %c %o %u %u %u %u %u %u %u",
+ buf, &type, &mode, &uid, &gid, &major, &minor,
+ &start, &increment, &count) < 0)
+@@ -144,8 +145,8 @@ static int interpret_table_entry(const c
+ buf, type, mode, uid, gid, major, minor, start,
+ increment, count);
+
+- len = strnlen(buf, 1024);
+- if (len == 1024)
++ len = strlen(buf);
++ if (len == 1023)
+ return err_msg("too long path");
+
+ if (!strcmp(buf, "/"))
+--- a/include/common.h
++++ b/include/common.h
+@@ -26,7 +26,6 @@
+ #include <string.h>
+ #include <fcntl.h>
+ #include <errno.h>
+-#include <features.h>
+ #include <inttypes.h>
+ #include "version.h"
+
+@@ -117,11 +116,6 @@ extern "C" {
+ fprintf(stderr, "%s: warning!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
+ } while(0)
+
+-#if defined(__UCLIBC__)
+-/* uClibc versions before 0.9.34 don't have rpmatch() */
+-#if __UCLIBC_MAJOR__ == 0 && \
+- (__UCLIBC_MINOR__ < 9 || \
+- (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 34))
+ #undef rpmatch
+ #define rpmatch __rpmatch
+ static inline int __rpmatch(const char *resp)
+@@ -129,8 +123,6 @@ static inline int __rpmatch(const char *
+ return (resp[0] == 'y' || resp[0] == 'Y') ? 1 :
+ (resp[0] == 'n' || resp[0] == 'N') ? 0 : -1;
+ }
+-#endif
+-#endif
+
+ /**
+ * prompt the user for confirmation
+--- a/include/mtd/ubifs-media.h
++++ b/include/mtd/ubifs-media.h
+@@ -33,7 +33,15 @@
+ #ifndef __UBIFS_MEDIA_H__
+ #define __UBIFS_MEDIA_H__
+
++#ifdef __linux__
+ #include <asm/byteorder.h>
++#else
++#include <stdint.h>
++typedef uint8_t __u8;
++typedef uint16_t __be16;
++typedef uint32_t __be32;
++typedef uint64_t __be64;
++#endif
+
+ /* UBIFS node magic number (must not have the padding byte first or last) */
+ #define UBIFS_NODE_MAGIC 0x06101831
diff --git a/tools/mtd-utils/patches/130-lzma_jffs2.patch b/tools/mtd-utils/patches/130-lzma_jffs2.patch
new file mode 100644
index 0000000..17f9978
--- /dev/null
+++ b/tools/mtd-utils/patches/130-lzma_jffs2.patch
@@ -0,0 +1,5030 @@
+--- a/Makefile
++++ b/Makefile
+@@ -4,6 +4,7 @@
+ VERSION = 1.5.1
+
+ CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS)
++CPPFLAGS += -I./include/linux/lzma
+
+ ifeq ($(WITHOUT_XATTR), 1)
+ CPPFLAGS += -DWITHOUT_XATTR
+@@ -84,7 +85,9 @@ $(BUILDDIR)/include/version.h.tmp:
+ #
+ # Utils in top level
+ #
+-obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o compr_lzo.o compr.o rbtree.o
++obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o $(if $(WITHOUT_LZO),,compr_lzo.o)\
++ compr_lzma.o lzma/LzFind.o lzma/LzmaEnc.o lzma/LzmaDec.o \
++ compr.o rbtree.o
+ LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+ LDLIBS_mkfs.jffs2 = -lz $(LZOLDLIBS)
+
+--- a/compr.c
++++ b/compr.c
+@@ -520,6 +520,9 @@ int jffs2_compressors_init(void)
+ #ifdef CONFIG_JFFS2_LZO
+ jffs2_lzo_init();
+ #endif
++#ifdef CONFIG_JFFS2_LZMA
++ jffs2_lzma_init();
++#endif
+ return 0;
+ }
+
+@@ -534,5 +537,8 @@ int jffs2_compressors_exit(void)
+ #ifdef CONFIG_JFFS2_LZO
+ jffs2_lzo_exit();
+ #endif
++#ifdef CONFIG_JFFS2_LZMA
++ jffs2_lzma_exit();
++#endif
+ return 0;
+ }
+--- a/compr.h
++++ b/compr.h
+@@ -18,13 +18,14 @@
+
+ #define CONFIG_JFFS2_ZLIB
+ #define CONFIG_JFFS2_RTIME
+-#define CONFIG_JFFS2_LZO
++#define CONFIG_JFFS2_LZMA
+
+ #define JFFS2_RUBINMIPS_PRIORITY 10
+ #define JFFS2_DYNRUBIN_PRIORITY 20
+ #define JFFS2_RTIME_PRIORITY 50
+-#define JFFS2_ZLIB_PRIORITY 60
+-#define JFFS2_LZO_PRIORITY 80
++#define JFFS2_LZMA_PRIORITY 70
++#define JFFS2_ZLIB_PRIORITY 80
++#define JFFS2_LZO_PRIORITY 90
+
+ #define JFFS2_COMPR_MODE_NONE 0
+ #define JFFS2_COMPR_MODE_PRIORITY 1
+@@ -115,5 +116,10 @@ void jffs2_rtime_exit(void);
+ int jffs2_lzo_init(void);
+ void jffs2_lzo_exit(void);
+ #endif
++#ifdef CONFIG_JFFS2_LZMA
++int jffs2_lzma_init(void);
++void jffs2_lzma_exit(void);
++#endif
++
+
+ #endif /* __JFFS2_COMPR_H__ */
+--- /dev/null
++++ b/compr_lzma.c
+@@ -0,0 +1,128 @@
++/*
++ * JFFS2 -- Journalling Flash File System, Version 2.
++ *
++ * For licensing information, see the file 'LICENCE' in this directory.
++ *
++ * JFFS2 wrapper to the LZMA C SDK
++ *
++ */
++
++#include <linux/lzma.h>
++#include "compr.h"
++
++#ifdef __KERNEL__
++ static DEFINE_MUTEX(deflate_mutex);
++#endif
++
++CLzmaEncHandle *p;
++Byte propsEncoded[LZMA_PROPS_SIZE];
++SizeT propsSize = sizeof(propsEncoded);
++
++STATIC void lzma_free_workspace(void)
++{
++ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc);
++}
++
++STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props)
++{
++ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL)
++ {
++ PRINT_ERROR("Failed to allocate lzma deflate workspace\n");
++ return -ENOMEM;
++ }
++
++ if (LzmaEnc_SetProps(p, props) != SZ_OK)
++ {
++ lzma_free_workspace();
++ return -1;
++ }
++
++ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK)
++ {
++ lzma_free_workspace();
++ return -1;
++ }
++
++ return 0;
++}
++
++STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out,
++ uint32_t *sourcelen, uint32_t *dstlen, void *model)
++{
++ SizeT compress_size = (SizeT)(*dstlen);
++ int ret;
++
++ #ifdef __KERNEL__
++ mutex_lock(&deflate_mutex);
++ #endif
++
++ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen,
++ 0, NULL, &lzma_alloc, &lzma_alloc);
++
++ #ifdef __KERNEL__
++ mutex_unlock(&deflate_mutex);
++ #endif
++
++ if (ret != SZ_OK)
++ return -1;
++
++ *dstlen = (uint32_t)compress_size;
++
++ return 0;
++}
++
++STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out,
++ uint32_t srclen, uint32_t destlen, void *model)
++{
++ int ret;
++ SizeT dl = (SizeT)destlen;
++ SizeT sl = (SizeT)srclen;
++ ELzmaStatus status;
++
++ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded,
++ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc);
++
++ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen)
++ return -1;
++
++ return 0;
++}
++
++static struct jffs2_compressor jffs2_lzma_comp = {
++ .priority = JFFS2_LZMA_PRIORITY,
++ .name = "lzma",
++ .compr = JFFS2_COMPR_LZMA,
++ .compress = &jffs2_lzma_compress,
++ .decompress = &jffs2_lzma_decompress,
++ .disabled = 0,
++};
++
++int INIT jffs2_lzma_init(void)
++{
++ int ret;
++ CLzmaEncProps props;
++ LzmaEncProps_Init(&props);
++
++ props.dictSize = LZMA_BEST_DICT(0x2000);
++ props.level = LZMA_BEST_LEVEL;
++ props.lc = LZMA_BEST_LC;
++ props.lp = LZMA_BEST_LP;
++ props.pb = LZMA_BEST_PB;
++ props.fb = LZMA_BEST_FB;
++
++ ret = lzma_alloc_workspace(&props);
++ if (ret < 0)
++ return ret;
++
++ ret = jffs2_register_compressor(&jffs2_lzma_comp);
++ if (ret)
++ lzma_free_workspace();
++
++ return ret;
++}
++
++void jffs2_lzma_exit(void)
++{
++ jffs2_unregister_compressor(&jffs2_lzma_comp);
++ lzma_free_workspace();
++}
+--- a/include/linux/jffs2.h
++++ b/include/linux/jffs2.h
+@@ -47,6 +47,7 @@
+ #define JFFS2_COMPR_DYNRUBIN 0x05
+ #define JFFS2_COMPR_ZLIB 0x06
+ #define JFFS2_COMPR_LZO 0x07
++#define JFFS2_COMPR_LZMA 0x08
+ /* Compatibility flags. */
+ #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */
+ #define JFFS2_NODE_ACCURATE 0x2000
+--- /dev/null
++++ b/include/linux/lzma.h
+@@ -0,0 +1,61 @@
++#ifndef __LZMA_H__
++#define __LZMA_H__
++
++#ifdef __KERNEL__
++ #include <linux/kernel.h>
++ #include <linux/sched.h>
++ #include <linux/slab.h>
++ #include <linux/vmalloc.h>
++ #include <linux/init.h>
++ #define LZMA_MALLOC vmalloc
++ #define LZMA_FREE vfree
++ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg)
++ #define INIT __init
++ #define STATIC static
++#else
++ #include <stdint.h>
++ #include <stdlib.h>
++ #include <stdio.h>
++ #include <unistd.h>
++ #include <string.h>
++ #include <errno.h>
++ #include <linux/jffs2.h>
++ #ifndef PAGE_SIZE
++ extern int page_size;
++ #define PAGE_SIZE page_size
++ #endif
++ #define LZMA_MALLOC malloc
++ #define LZMA_FREE free
++ #define PRINT_ERROR(msg) fprintf(stderr, msg)
++ #define INIT
++ #define STATIC
++#endif
++
++#include "lzma/LzmaDec.h"
++#include "lzma/LzmaEnc.h"
++
++#define LZMA_BEST_LEVEL (9)
++#define LZMA_BEST_LC (0)
++#define LZMA_BEST_LP (0)
++#define LZMA_BEST_PB (0)
++#define LZMA_BEST_FB (273)
++
++#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2)
++
++static void *p_lzma_malloc(void *p, size_t size)
++{
++ if (size == 0)
++ return NULL;
++
++ return LZMA_MALLOC(size);
++}
++
++static void p_lzma_free(void *p, void *address)
++{
++ if (address != NULL)
++ LZMA_FREE(address);
++}
++
++static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free};
++
++#endif
+--- /dev/null
++++ b/include/linux/lzma/LzFind.h
+@@ -0,0 +1,116 @@
++/* LzFind.h -- Match finder for LZ algorithms
++2008-04-04
++Copyright (c) 1999-2008 Igor Pavlov
++You can use any of the following license options:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ 3) Common Development and Distribution License (CDDL) Version 1.0
++ 4) Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to this file,
++ while you keep this file unmodified.
++*/
++
++#ifndef __LZFIND_H
++#define __LZFIND_H
++
++#include "Types.h"
++
++typedef UInt32 CLzRef;
++
++typedef struct _CMatchFinder
++{
++ Byte *buffer;
++ UInt32 pos;
++ UInt32 posLimit;
++ UInt32 streamPos;
++ UInt32 lenLimit;
++
++ UInt32 cyclicBufferPos;
++ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
++
++ UInt32 matchMaxLen;
++ CLzRef *hash;
++ CLzRef *son;
++ UInt32 hashMask;
++ UInt32 cutValue;
++
++ Byte *bufferBase;
++ ISeqInStream *stream;
++ int streamEndWasReached;
++
++ UInt32 blockSize;
++ UInt32 keepSizeBefore;
++ UInt32 keepSizeAfter;
++
++ UInt32 numHashBytes;
++ int directInput;
++ int btMode;
++ /* int skipModeBits; */
++ int bigHash;
++ UInt32 historySize;
++ UInt32 fixedHashSize;
++ UInt32 hashSizeSum;
++ UInt32 numSons;
++ SRes result;
++ UInt32 crc[256];
++} CMatchFinder;
++
++#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
++#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
++
++#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
++
++int MatchFinder_NeedMove(CMatchFinder *p);
++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
++void MatchFinder_MoveBlock(CMatchFinder *p);
++void MatchFinder_ReadIfRequired(CMatchFinder *p);
++
++void MatchFinder_Construct(CMatchFinder *p);
++
++/* Conditions:
++ historySize <= 3 GB
++ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
++*/
++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
++ ISzAlloc *alloc);
++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
++
++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
++ UInt32 *distances, UInt32 maxLen);
++
++/*
++Conditions:
++ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
++ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
++*/
++
++typedef void (*Mf_Init_Func)(void *object);
++typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
++typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
++typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
++typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
++typedef void (*Mf_Skip_Func)(void *object, UInt32);
++
++typedef struct _IMatchFinder
++{
++ Mf_Init_Func Init;
++ Mf_GetIndexByte_Func GetIndexByte;
++ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
++ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
++ Mf_GetMatches_Func GetMatches;
++ Mf_Skip_Func Skip;
++} IMatchFinder;
++
++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
++
++void MatchFinder_Init(CMatchFinder *p);
++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
++
++#endif
+--- /dev/null
++++ b/include/linux/lzma/LzHash.h
+@@ -0,0 +1,56 @@
++/* LzHash.h -- HASH functions for LZ algorithms
++2008-03-26
++Copyright (c) 1999-2008 Igor Pavlov
++Read LzFind.h for license options */
++
++#ifndef __LZHASH_H
++#define __LZHASH_H
++
++#define kHash2Size (1 << 10)
++#define kHash3Size (1 << 16)
++#define kHash4Size (1 << 20)
++
++#define kFix3HashSize (kHash2Size)
++#define kFix4HashSize (kHash2Size + kHash3Size)
++#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
++
++#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
++
++#define HASH3_CALC { \
++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
++ hash2Value = temp & (kHash2Size - 1); \
++ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
++
++#define HASH4_CALC { \
++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
++ hash2Value = temp & (kHash2Size - 1); \
++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
++ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
++
++#define HASH5_CALC { \
++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
++ hash2Value = temp & (kHash2Size - 1); \
++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
++ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
++ hash4Value &= (kHash4Size - 1); }
++
++/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
++#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
++
++
++#define MT_HASH2_CALC \
++ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
++
++#define MT_HASH3_CALC { \
++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
++ hash2Value = temp & (kHash2Size - 1); \
++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
++
++#define MT_HASH4_CALC { \
++ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
++ hash2Value = temp & (kHash2Size - 1); \
++ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
++ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
++
++#endif
+--- /dev/null
++++ b/include/linux/lzma/LzmaDec.h
+@@ -0,0 +1,232 @@
++/* LzmaDec.h -- LZMA Decoder
++2008-04-29
++Copyright (c) 1999-2008 Igor Pavlov
++You can use any of the following license options:
++ 1) GNU Lesser General Public License (GNU LGPL)
++ 2) Common Public License (CPL)
++ 3) Common Development and Distribution License (CDDL) Version 1.0
++ 4) Igor Pavlov, as the author of this code, expressly permits you to
++ statically or dynamically link your code (or bind by name) to this file,
++ while you keep this file unmodified.
++*/
++
++#ifndef __LZMADEC_H
++#define __LZMADEC_H
++
++#include "Types.h"
++
++/* #define _LZMA_PROB32 */
++/* _LZMA_PROB32 can increase the speed on some CPUs,
++ but memory usage for CLzmaDec::probs will be doubled in that case */
++
++#ifdef _LZMA_PROB32
++#define CLzmaProb UInt32
++#else
++#define CLzmaProb UInt16
++#endif
++
++
++/* ---------- LZMA Properties ---------- */
++
++#define LZMA_PROPS_SIZE 5
++
++typedef struct _CLzmaProps
++{
++ unsigned lc, lp, pb;
++ UInt32 dicSize;
++} CLzmaProps;
++
++/* LzmaProps_Decode - decodes properties
++Returns:
++ SZ_OK
++ SZ_ERROR_UNSUPPORTED - Unsupported properties
++*/
++
++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
++
++
++/* ---------- LZMA Decoder state ---------- */
++
++/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
++ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
++
++#define LZMA_REQUIRED_INPUT_MAX 20
++
++typedef struct
++{
++ CLzmaProps prop;
++ CLzmaProb *probs;
++ Byte *dic;
++ const Byte *buf;
++ UInt32 range, code;
++ SizeT dicPos;
++ SizeT dicBufSize;
++ UInt32 processedPos;
++ UInt32 checkDicSize;
++ unsigned state;
++ UInt32 reps[4];
++ unsigned remainLen;
++ int needFlush;
++ int needInitState;
++ UInt32 numProbs;
++ unsigned tempBufSize;
++ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
++} CLzmaDec;
++
++#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
++
++void LzmaDec_Init(CLzmaDec *p);
++
++/* There are two types of LZMA streams:
++ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
++ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
++
++typedef enum
++{
++ LZMA_FINISH_ANY, /* finish at any point */
++ LZMA_FINISH_END /* block must be finished at the end */
++} ELzmaFinishMode;
++
++/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
++
++ You must use LZMA_FINISH_END, when you know that current output buffer
++ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
++
++ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
++ and output value of destLen will be less than output buffer size limit.
++ You can check status result also.
++
++ You can use multiple checks to test data integrity after full decompression:
++ 1) Check Result and "status" variable.
++ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
++ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
++ You must use correct finish mode in that case. */
++
++typedef enum
++{
++ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
++ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
++ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
++ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
++} ELzmaStatus;
++
++/* ELzmaStatus is used only as output value for function call */
++
++
++/* ---------- Interfaces ---------- */
++
++/* There are 3 levels of interfaces:
++ 1) Dictionary Interface
++ 2) Buffer Interface
++ 3) One Call Interface
++ You can select any of these interfaces, but don't mix functions from different
++ groups for same object. */
++
++
++/* There are two variants to allocate state for Dictionary Interface:
++ 1) LzmaDec_Allocate / LzmaDec_Free
++ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
++ You can use variant 2, if you set dictionary buffer manually.
++ For Buffer Interface you must always use variant 1.
++
++LzmaDec_Allocate* can return:
++ SZ_OK
++ SZ_ERROR_MEM - Memory allocation error
++ SZ_ERROR_UNSUPPORTED - Unsupported properties
++*/
++
++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
++
++SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
++void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
++
++/* ---------- Dictionary Interface ---------- */
++
++/* You can use it, if you want to eliminate the overhead for data copying from
++ dictionary to some other external buffer.
++ You must work with CLzmaDec variables directly in this interface.
++
++ STEPS:
++ LzmaDec_Constr()
++ LzmaDec_Allocate()
++ for (each new stream)
++ {
++ LzmaDec_Init()
++ while (it needs more decompression)
++ {
++ LzmaDec_DecodeToDic()
++ use data from CLzmaDec::dic and update CLzmaDec::dicPos
++ }
++ }
++ LzmaDec_Free()
++*/
++
++/* LzmaDec_DecodeToDic
++
++ The decoding to internal dictionary buffer (CLzmaDec::dic).
++ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
++
++finishMode:
++ It has meaning only if the decoding reaches output limit (dicLimit).
++ LZMA_FINISH_ANY - Decode just dicLimit bytes.
++ LZMA_FINISH_END - Stream must be finished after dicLimit.
++
++Returns:
++ SZ_OK
++ status:
++ LZMA_STATUS_FINISHED_WITH_MARK
++ LZMA_STATUS_NOT_FINISHED
++ LZMA_STATUS_NEEDS_MORE_INPUT
++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
++ SZ_ERROR_DATA - Data error
++*/
++
++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
++
++
++/* ---------- Buffer Interface ---------- */
++
++/* It's zlib-like interface.
++ See LzmaDec_DecodeToDic description for information about STEPS and return results,
++ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
++ to work with CLzmaDec variables manually.
++
++finishMode:
++ It has meaning only if the decoding reaches output limit (*destLen).
++ LZMA_FINISH_ANY - Decode just destLen bytes.
++ LZMA_FINISH_END - Stream must be finished after (*destLen).
++*/
++
++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
++ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
++
++
++/* ---------- One Call Interface ---------- */
++
++/* LzmaDecode
++
++finishMode:
++ It has meaning only if the decoding reaches output limit (*destLen).
++ LZMA_FINISH_ANY - Decode just destLen bytes.
++ LZMA_FINISH_END - Stream must be finished after (*destLen).
++
++Returns:
++ SZ_OK
++ status:
++ LZMA_STATUS_FINISHED_WITH_MARK
++ LZMA_STATUS_NOT_FINISHED
++ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
++ SZ_ERROR_DATA - Data error
++ SZ_ERROR_MEM - Memory allocation error
++ SZ_ERROR_UNSUPPORTED - Unsupported properties
++ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
++*/
++
++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
++ ELzmaStatus *status, ISzAlloc *alloc);
++
++#endif
+--- /dev/null
++++ b/include/linux/lzma/LzmaEnc.h
+@@ -0,0 +1,74 @@
++/* LzmaEnc.h -- LZMA Encoder
++2008-04-27
++Copyright (c) 1999-2008 Igor Pavlov
++Read LzFind.h for license options */
++
++#ifndef __LZMAENC_H
++#define __LZMAENC_H
++
++#include "Types.h"
++
++#define LZMA_PROPS_SIZE 5
++
++typedef struct _CLzmaEncProps
++{
++ int level; /* 0 <= level <= 9 */
++ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
++ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
++ default = (1 << 24) */
++ int lc; /* 0 <= lc <= 8, default = 3 */
++ int lp; /* 0 <= lp <= 4, default = 0 */
++ int pb; /* 0 <= pb <= 4, default = 2 */
++ int algo; /* 0 - fast, 1 - normal, default = 1 */
++ int fb; /* 5 <= fb <= 273, default = 32 */
++ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
++ int numHashBytes; /* 2, 3 or 4, default = 4 */
++ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
++ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
++ int numThreads; /* 1 or 2, default = 2 */
++} CLzmaEncProps;
++
++void LzmaEncProps_Init(CLzmaEncProps *p);
++void LzmaEncProps_Normalize(CLzmaEncProps *p);
++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
++
++
++/* ---------- CLzmaEncHandle Interface ---------- */
++
++/* LzmaEnc_* functions can return the following exit codes:
++Returns:
++ SZ_OK - OK
++ SZ_ERROR_MEM - Memory allocation error
++ SZ_ERROR_PARAM - Incorrect paramater in props
++ SZ_ERROR_WRITE - Write callback error.
++ SZ_ERROR_PROGRESS - some break from progress callback
++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
++*/
++
++typedef void * CLzmaEncHandle;
++
++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
++SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
++SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
++SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
++SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
++
++/* ---------- One Call Interface ---------- */
++
++/* LzmaEncode
++Return code:
++ SZ_OK - OK
++ SZ_ERROR_MEM - Memory allocation error
++ SZ_ERROR_PARAM - Incorrect paramater
++ SZ_ERROR_OUTPUT_EOF - output buffer overflow
++ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
++*/
++
++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
++
++#endif
+--- /dev/null
++++ b/include/linux/lzma/Types.h
+@@ -0,0 +1,130 @@
++/* Types.h -- Basic types
++2008-04-11
++Igor Pavlov
++Public domain */
++
++#ifndef __7Z_TYPES_H
++#define __7Z_TYPES_H
++
++#define SZ_OK 0
++
++#define SZ_ERROR_DATA 1
++#define SZ_ERROR_MEM 2
++#define SZ_ERROR_CRC 3
++#define SZ_ERROR_UNSUPPORTED 4
++#define SZ_ERROR_PARAM 5
++#define SZ_ERROR_INPUT_EOF 6
++#define SZ_ERROR_OUTPUT_EOF 7
++#define SZ_ERROR_READ 8
++#define SZ_ERROR_WRITE 9
++#define SZ_ERROR_PROGRESS 10
++#define SZ_ERROR_FAIL 11
++#define SZ_ERROR_THREAD 12
++
++#define SZ_ERROR_ARCHIVE 16
++#define SZ_ERROR_NO_ARCHIVE 17
++
++typedef int SRes;
++
++#ifndef RINOK
++#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
++#endif
++
++typedef unsigned char Byte;
++typedef short Int16;
++typedef unsigned short UInt16;
++
++#ifdef _LZMA_UINT32_IS_ULONG
++typedef long Int32;
++typedef unsigned long UInt32;
++#else
++typedef int Int32;
++typedef unsigned int UInt32;
++#endif
++
++/* #define _SZ_NO_INT_64 */
++/* define it if your compiler doesn't support 64-bit integers */
++
++#ifdef _SZ_NO_INT_64
++
++typedef long Int64;
++typedef unsigned long UInt64;
++
++#else
++
++#if defined(_MSC_VER) || defined(__BORLANDC__)
++typedef __int64 Int64;
++typedef unsigned __int64 UInt64;
++#else
++typedef long long int Int64;
++typedef unsigned long long int UInt64;
++#endif
++
++#endif
++
++#ifdef _LZMA_NO_SYSTEM_SIZE_T
++typedef UInt32 SizeT;
++#else
++#include <stddef.h>
++typedef size_t SizeT;
++#endif
++
++typedef int Bool;
++#define True 1
++#define False 0
++
++
++#ifdef _MSC_VER
++
++#if _MSC_VER >= 1300
++#define MY_NO_INLINE __declspec(noinline)
++#else
++#define MY_NO_INLINE
++#endif
++
++#define MY_CDECL __cdecl
++#define MY_STD_CALL __stdcall
++#define MY_FAST_CALL MY_NO_INLINE __fastcall
++
++#else
++
++#define MY_CDECL
++#define MY_STD_CALL
++#define MY_FAST_CALL
++
++#endif
++
++
++/* The following interfaces use first parameter as pointer to structure */
++
++typedef struct
++{
++ SRes (*Read)(void *p, void *buf, size_t *size);
++ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
++ (output(*size) < input(*size)) is allowed */
++} ISeqInStream;
++
++typedef struct
++{
++ size_t (*Write)(void *p, const void *buf, size_t size);
++ /* Returns: result - the number of actually written bytes.
++ (result < size) means error */
++} ISeqOutStream;
++
++typedef struct
++{
++ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
++ /* Returns: result. (result != SZ_OK) means break.
++ Value (UInt64)(Int64)-1 for size means unknown value. */
++} ICompressProgress;
++
++typedef struct
++{
++ void *(*Alloc)(void *p, size_t size);
++ void (*Free)(void *p, void *address); /* address can be 0 */
++} ISzAlloc;
++
++#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
++#define IAlloc_Free(p, a) (p)->Free((p), a)
++
++#endif
+--- /dev/null
++++ b/lzma/LzFind.c
+@@ -0,0 +1,753 @@
++/* LzFind.c -- Match finder for LZ algorithms
++2008-04-04
++Copyright (c) 1999-2008 Igor Pavlov
++Read LzFind.h for license options */
++
++#include <string.h>
++
++#include "LzFind.h"
++#include "LzHash.h"
++
++#define kEmptyHashValue 0
++#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
++#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
++#define kNormalizeMask (~(kNormalizeStepMin - 1))
++#define kMaxHistorySize ((UInt32)3 << 30)
++
++#define kStartMaxLen 3
++
++static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
++{
++ if (!p->directInput)
++ {
++ alloc->Free(alloc, p->bufferBase);
++ p->bufferBase = 0;
++ }
++}
++
++/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
++
++static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
++{
++ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
++ if (p->directInput)
++ {
++ p->blockSize = blockSize;
++ return 1;
++ }
++ if (p->bufferBase == 0 || p->blockSize != blockSize)
++ {
++ LzInWindow_Free(p, alloc);
++ p->blockSize = blockSize;
++ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
++ }
++ return (p->bufferBase != 0);
++}
++
++Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
++Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
++
++UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
++
++void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
++{
++ p->posLimit -= subValue;
++ p->pos -= subValue;
++ p->streamPos -= subValue;
++}
++
++static void MatchFinder_ReadBlock(CMatchFinder *p)
++{
++ if (p->streamEndWasReached || p->result != SZ_OK)
++ return;
++ for (;;)
++ {
++ Byte *dest = p->buffer + (p->streamPos - p->pos);
++ size_t size = (p->bufferBase + p->blockSize - dest);
++ if (size == 0)
++ return;
++ p->result = p->stream->Read(p->stream, dest, &size);
++ if (p->result != SZ_OK)
++ return;
++ if (size == 0)
++ {
++ p->streamEndWasReached = 1;
++ return;
++ }
++ p->streamPos += (UInt32)size;
++ if (p->streamPos - p->pos > p->keepSizeAfter)
++ return;
++ }
++}
++
++void MatchFinder_MoveBlock(CMatchFinder *p)
++{
++ memmove(p->bufferBase,
++ p->buffer - p->keepSizeBefore,
++ (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
++ p->buffer = p->bufferBase + p->keepSizeBefore;
++}
++
++int MatchFinder_NeedMove(CMatchFinder *p)
++{
++ /* if (p->streamEndWasReached) return 0; */
++ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
++}
++
++void MatchFinder_ReadIfRequired(CMatchFinder *p)
++{
++ if (p->streamEndWasReached)
++ return;
++ if (p->keepSizeAfter >= p->streamPos - p->pos)
++ MatchFinder_ReadBlock(p);
++}
++
++static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
++{
++ if (MatchFinder_NeedMove(p))
++ MatchFinder_MoveBlock(p);
++ MatchFinder_ReadBlock(p);
++}
++
++static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
++{
++ p->cutValue = 32;
++ p->btMode = 1;
++ p->numHashBytes = 4;
++ /* p->skipModeBits = 0; */
++ p->directInput = 0;
++ p->bigHash = 0;
++}
++
++#define kCrcPoly 0xEDB88320
++
++void MatchFinder_Construct(CMatchFinder *p)
++{
++ UInt32 i;
++ p->bufferBase = 0;
++ p->directInput = 0;
++ p->hash = 0;
++ MatchFinder_SetDefaultSettings(p);
++
++ for (i = 0; i < 256; i++)
++ {
++ UInt32 r = i;
++ int j;
++ for (j = 0; j < 8; j++)
++ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
++ p->crc[i] = r;
++ }
++}
++
++static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
++{
++ alloc->Free(alloc, p->hash);
++ p->hash = 0;
++}
++
++void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
++{
++ MatchFinder_FreeThisClassMemory(p, alloc);
++ LzInWindow_Free(p, alloc);
++}
++
++static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
++{
++ size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
++ if (sizeInBytes / sizeof(CLzRef) != num)
++ return 0;
++ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
++}
++
++int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
++ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
++ ISzAlloc *alloc)
++{
++ UInt32 sizeReserv;
++ if (historySize > kMaxHistorySize)
++ {
++ MatchFinder_Free(p, alloc);
++ return 0;
++ }
++ sizeReserv = historySize >> 1;
++ if (historySize > ((UInt32)2 << 30))
++ sizeReserv = historySize >> 2;
++ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
++
++ p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
++ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
++ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
++ if (LzInWindow_Create(p, sizeReserv, alloc))
++ {
++ UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
++ UInt32 hs;
++ p->matchMaxLen = matchMaxLen;
++ {
++ p->fixedHashSize = 0;
++ if (p->numHashBytes == 2)
++ hs = (1 << 16) - 1;
++ else
++ {
++ hs = historySize - 1;
++ hs |= (hs >> 1);
++ hs |= (hs >> 2);
++ hs |= (hs >> 4);
++ hs |= (hs >> 8);
++ hs >>= 1;
++ /* hs >>= p->skipModeBits; */
++ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
++ if (hs > (1 << 24))
++ {
++ if (p->numHashBytes == 3)
++ hs = (1 << 24) - 1;
++ else
++ hs >>= 1;
++ }
++ }
++ p->hashMask = hs;
++ hs++;
++ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
++ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
++ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
++ hs += p->fixedHashSize;
++ }
++
++ {
++ UInt32 prevSize = p->hashSizeSum + p->numSons;
++ UInt32 newSize;
++ p->historySize = historySize;
++ p->hashSizeSum = hs;
++ p->cyclicBufferSize = newCyclicBufferSize;
++ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
++ newSize = p->hashSizeSum + p->numSons;
++ if (p->hash != 0 && prevSize == newSize)
++ return 1;
++ MatchFinder_FreeThisClassMemory(p, alloc);
++ p->hash = AllocRefs(newSize, alloc);
++ if (p->hash != 0)
++ {
++ p->son = p->hash + p->hashSizeSum;
++ return 1;
++ }
++ }
++ }
++ MatchFinder_Free(p, alloc);
++ return 0;
++}
++
++static void MatchFinder_SetLimits(CMatchFinder *p)
++{
++ UInt32 limit = kMaxValForNormalize - p->pos;
++ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
++ if (limit2 < limit)
++ limit = limit2;
++ limit2 = p->streamPos - p->pos;
++ if (limit2 <= p->keepSizeAfter)
++ {
++ if (limit2 > 0)
++ limit2 = 1;
++ }
++ else
++ limit2 -= p->keepSizeAfter;
++ if (limit2 < limit)
++ limit = limit2;
++ {
++ UInt32 lenLimit = p->streamPos - p->pos;
++ if (lenLimit > p->matchMaxLen)
++ lenLimit = p->matchMaxLen;
++ p->lenLimit = lenLimit;
++ }
++ p->posLimit = p->pos + limit;
++}
++
++void MatchFinder_Init(CMatchFinder *p)
++{
++ UInt32 i;
++ for(i = 0; i < p->hashSizeSum; i++)
++ p->hash[i] = kEmptyHashValue;
++ p->cyclicBufferPos = 0;
++ p->buffer = p->bufferBase;
++ p->pos = p->streamPos = p->cyclicBufferSize;
++ p->result = SZ_OK;
++ p->streamEndWasReached = 0;
++ MatchFinder_ReadBlock(p);
++ MatchFinder_SetLimits(p);
++}
++
++static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
++{
++ return (p->pos - p->historySize - 1) & kNormalizeMask;
++}
++
++void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
++{
++ UInt32 i;
++ for (i = 0; i < numItems; i++)
++ {
++ UInt32 value = items[i];
++ if (value <= subValue)
++ value = kEmptyHashValue;
++ else
++ value -= subValue;
++ items[i] = value;
++ }
++}
++
++static void MatchFinder_Normalize(CMatchFinder *p)
++{
++ UInt32 subValue = MatchFinder_GetSubValue(p);
++ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
++ MatchFinder_ReduceOffsets(p, subValue);
++}
++
++static void MatchFinder_CheckLimits(CMatchFinder *p)
++{
++ if (p->pos == kMaxValForNormalize)
++ MatchFinder_Normalize(p);
++ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
++ MatchFinder_CheckAndMoveAndRead(p);
++ if (p->cyclicBufferPos == p->cyclicBufferSize)
++ p->cyclicBufferPos = 0;
++ MatchFinder_SetLimits(p);
++}
++
++static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
++ UInt32 *distances, UInt32 maxLen)
++{
++ son[_cyclicBufferPos] = curMatch;
++ for (;;)
++ {
++ UInt32 delta = pos - curMatch;
++ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
++ return distances;
++ {
++ const Byte *pb = cur - delta;
++ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
++ if (pb[maxLen] == cur[maxLen] && *pb == *cur)
++ {
++ UInt32 len = 0;
++ while(++len != lenLimit)
++ if (pb[len] != cur[len])
++ break;
++ if (maxLen < len)
++ {
++ *distances++ = maxLen = len;
++ *distances++ = delta - 1;
++ if (len == lenLimit)
++ return distances;
++ }
++ }
++ }
++ }
++}
++
++UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
++ UInt32 *distances, UInt32 maxLen)
++{
++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
++ UInt32 len0 = 0, len1 = 0;
++ for (;;)
++ {
++ UInt32 delta = pos - curMatch;
++ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
++ {
++ *ptr0 = *ptr1 = kEmptyHashValue;
++ return distances;
++ }
++ {
++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
++ const Byte *pb = cur - delta;
++ UInt32 len = (len0 < len1 ? len0 : len1);
++ if (pb[len] == cur[len])
++ {
++ if (++len != lenLimit && pb[len] == cur[len])
++ while(++len != lenLimit)
++ if (pb[len] != cur[len])
++ break;
++ if (maxLen < len)
++ {
++ *distances++ = maxLen = len;
++ *distances++ = delta - 1;
++ if (len == lenLimit)
++ {
++ *ptr1 = pair[0];
++ *ptr0 = pair[1];
++ return distances;
++ }
++ }
++ }
++ if (pb[len] < cur[len])
++ {
++ *ptr1 = curMatch;
++ ptr1 = pair + 1;
++ curMatch = *ptr1;
++ len1 = len;
++ }
++ else
++ {
++ *ptr0 = curMatch;
++ ptr0 = pair;
++ curMatch = *ptr0;
++ len0 = len;
++ }
++ }
++ }
++}
++
++static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
++ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
++{
++ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
++ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
++ UInt32 len0 = 0, len1 = 0;
++ for (;;)
++ {
++ UInt32 delta = pos - curMatch;
++ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
++ {
++ *ptr0 = *ptr1 = kEmptyHashValue;
++ return;
++ }
++ {
++ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
++ const Byte *pb = cur - delta;
++ UInt32 len = (len0 < len1 ? len0 : len1);
++ if (pb[len] == cur[len])
++ {
++ while(++len != lenLimit)
++ if (pb[len] != cur[len])
++ break;
++ {
++ if (len == lenLimit)
++ {
++ *ptr1 = pair[0];
++ *ptr0 = pair[1];
++ return;
++ }
++ }
++ }
++ if (pb[len] < cur[len])
++ {
++ *ptr1 = curMatch;
++ ptr1 = pair + 1;
++ curMatch = *ptr1;
++ len1 = len;
++ }
++ else
++ {
++ *ptr0 = curMatch;
++ ptr0 = pair;
++ curMatch = *ptr0;
++ len0 = len;
++ }
++ }
++ }
++}
++
++#define MOVE_POS \
++ ++p->cyclicBufferPos; \
++ p->buffer++; \
++ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
++
++#define MOVE_POS_RET MOVE_POS return offset;
++
++static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
++
++#define GET_MATCHES_HEADER2(minLen, ret_op) \
++ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
++ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
++ cur = p->buffer;
++
++#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
++#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
++
++#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
++
++#define GET_MATCHES_FOOTER(offset, maxLen) \
++ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
++ distances + offset, maxLen) - distances); MOVE_POS_RET;
++
++#define SKIP_FOOTER \
++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
++
++static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
++{
++ UInt32 offset;
++ GET_MATCHES_HEADER(2)
++ HASH2_CALC;
++ curMatch = p->hash[hashValue];
++ p->hash[hashValue] = p->pos;
++ offset = 0;
++ GET_MATCHES_FOOTER(offset, 1)
++}
++
++UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
++{
++ UInt32 offset;
++ GET_MATCHES_HEADER(3)
++ HASH_ZIP_CALC;
++ curMatch = p->hash[hashValue];
++ p->hash[hashValue] = p->pos;
++ offset = 0;
++ GET_MATCHES_FOOTER(offset, 2)
++}
++
++static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
++{
++ UInt32 hash2Value, delta2, maxLen, offset;
++ GET_MATCHES_HEADER(3)
++
++ HASH3_CALC;
++
++ delta2 = p->pos - p->hash[hash2Value];
++ curMatch = p->hash[kFix3HashSize + hashValue];
++
++ p->hash[hash2Value] =
++ p->hash[kFix3HashSize + hashValue] = p->pos;
++
++
++ maxLen = 2;
++ offset = 0;
++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
++ {
++ for (; maxLen != lenLimit; maxLen++)
++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
++ break;
++ distances[0] = maxLen;
++ distances[1] = delta2 - 1;
++ offset = 2;
++ if (maxLen == lenLimit)
++ {
++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
++ MOVE_POS_RET;
++ }
++ }
++ GET_MATCHES_FOOTER(offset, maxLen)
++}
++
++static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
++{
++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
++ GET_MATCHES_HEADER(4)
++
++ HASH4_CALC;
++
++ delta2 = p->pos - p->hash[ hash2Value];
++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
++ curMatch = p->hash[kFix4HashSize + hashValue];
++
++ p->hash[ hash2Value] =
++ p->hash[kFix3HashSize + hash3Value] =
++ p->hash[kFix4HashSize + hashValue] = p->pos;
++
++ maxLen = 1;
++ offset = 0;
++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
++ {
++ distances[0] = maxLen = 2;
++ distances[1] = delta2 - 1;
++ offset = 2;
++ }
++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
++ {
++ maxLen = 3;
++ distances[offset + 1] = delta3 - 1;
++ offset += 2;
++ delta2 = delta3;
++ }
++ if (offset != 0)
++ {
++ for (; maxLen != lenLimit; maxLen++)
++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
++ break;
++ distances[offset - 2] = maxLen;
++ if (maxLen == lenLimit)
++ {
++ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
++ MOVE_POS_RET;
++ }
++ }
++ if (maxLen < 3)
++ maxLen = 3;
++ GET_MATCHES_FOOTER(offset, maxLen)
++}
++
++static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
++{
++ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
++ GET_MATCHES_HEADER(4)
++
++ HASH4_CALC;
++
++ delta2 = p->pos - p->hash[ hash2Value];
++ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
++ curMatch = p->hash[kFix4HashSize + hashValue];
++
++ p->hash[ hash2Value] =
++ p->hash[kFix3HashSize + hash3Value] =
++ p->hash[kFix4HashSize + hashValue] = p->pos;
++
++ maxLen = 1;
++ offset = 0;
++ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
++ {
++ distances[0] = maxLen = 2;
++ distances[1] = delta2 - 1;
++ offset = 2;
++ }
++ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
++ {
++ maxLen = 3;
++ distances[offset + 1] = delta3 - 1;
++ offset += 2;
++ delta2 = delta3;
++ }
++ if (offset != 0)
++ {
++ for (; maxLen != lenLimit; maxLen++)
++ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
++ break;
++ distances[offset - 2] = maxLen;
++ if (maxLen == lenLimit)
++ {
++ p->son[p->cyclicBufferPos] = curMatch;
++ MOVE_POS_RET;
++ }
++ }
++ if (maxLen < 3)
++ maxLen = 3;
++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
++ distances + offset, maxLen) - (distances));
++ MOVE_POS_RET
++}
++
++UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
++{
++ UInt32 offset;
++ GET_MATCHES_HEADER(3)
++ HASH_ZIP_CALC;
++ curMatch = p->hash[hashValue];
++ p->hash[hashValue] = p->pos;
++ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
++ distances, 2) - (distances));
++ MOVE_POS_RET
++}
++
++static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
++{
++ do
++ {
++ SKIP_HEADER(2)
++ HASH2_CALC;
++ curMatch = p->hash[hashValue];
++ p->hash[hashValue] = p->pos;
++ SKIP_FOOTER
++ }
++ while (--num != 0);
++}
++
++void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
++{
++ do
++ {
++ SKIP_HEADER(3)
++ HASH_ZIP_CALC;
++ curMatch = p->hash[hashValue];
++ p->hash[hashValue] = p->pos;
++ SKIP_FOOTER
++ }
++ while (--num != 0);
++}
++
++static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
++{
++ do
++ {
++ UInt32 hash2Value;
++ SKIP_HEADER(3)
++ HASH3_CALC;
++ curMatch = p->hash[kFix3HashSize + hashValue];
++ p->hash[hash2Value] =
++ p->hash[kFix3HashSize + hashValue] = p->pos;
++ SKIP_FOOTER
++ }
++ while (--num != 0);
++}
++
++static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
++{
++ do
++ {
++ UInt32 hash2Value, hash3Value;
++ SKIP_HEADER(4)
++ HASH4_CALC;
++ curMatch = p->hash[kFix4HashSize + hashValue];
++ p->hash[ hash2Value] =
++ p->hash[kFix3HashSize + hash3Value] = p->pos;
++ p->hash[kFix4HashSize + hashValue] = p->pos;
++ SKIP_FOOTER
++ }
++ while (--num != 0);
++}
++
++static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
++{
++ do
++ {
++ UInt32 hash2Value, hash3Value;
++ SKIP_HEADER(4)
++ HASH4_CALC;
++ curMatch = p->hash[kFix4HashSize + hashValue];
++ p->hash[ hash2Value] =
++ p->hash[kFix3HashSize + hash3Value] =
++ p->hash[kFix4HashSize + hashValue] = p->pos;
++ p->son[p->cyclicBufferPos] = curMatch;
++ MOVE_POS
++ }
++ while (--num != 0);
++}
++
++void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
++{
++ do
++ {
++ SKIP_HEADER(3)
++ HASH_ZIP_CALC;
++ curMatch = p->hash[hashValue];
++ p->hash[hashValue] = p->pos;
++ p->son[p->cyclicBufferPos] = curMatch;
++ MOVE_POS
++ }
++ while (--num != 0);
++}
++
++void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
++{
++ vTable->Init = (Mf_Init_Func)MatchFinder_Init;
++ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
++ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
++ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
++ if (!p->btMode)
++ {
++ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
++ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
++ }
++ else if (p->numHashBytes == 2)
++ {
++ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
++ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
++ }
++ else if (p->numHashBytes == 3)
++ {
++ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
++ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
++ }
++ else
++ {
++ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
++ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
++ }
++}
+--- /dev/null
++++ b/lzma/LzmaDec.c
+@@ -0,0 +1,1014 @@
++/* LzmaDec.c -- LZMA Decoder
++2008-04-29
++Copyright (c) 1999-2008 Igor Pavlov
++Read LzmaDec.h for license options */
++
++#include "LzmaDec.h"
++
++#include <string.h>
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++#define RC_INIT_SIZE 5
++
++#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
++
++#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
++#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
++#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
++#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
++ { UPDATE_0(p); i = (i + i); A0; } else \
++ { UPDATE_1(p); i = (i + i) + 1; A1; }
++#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
++
++#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
++#define TREE_DECODE(probs, limit, i) \
++ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
++
++/* #define _LZMA_SIZE_OPT */
++
++#ifdef _LZMA_SIZE_OPT
++#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
++#else
++#define TREE_6_DECODE(probs, i) \
++ { i = 1; \
++ TREE_GET_BIT(probs, i); \
++ TREE_GET_BIT(probs, i); \
++ TREE_GET_BIT(probs, i); \
++ TREE_GET_BIT(probs, i); \
++ TREE_GET_BIT(probs, i); \
++ TREE_GET_BIT(probs, i); \
++ i -= 0x40; }
++#endif
++
++#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
++
++#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
++#define UPDATE_0_CHECK range = bound;
++#define UPDATE_1_CHECK range -= bound; code -= bound;
++#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
++ { UPDATE_0_CHECK; i = (i + i); A0; } else \
++ { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
++#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
++#define TREE_DECODE_CHECK(probs, limit, i) \
++ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while(i < limit); i -= limit; }
++
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
++
++
++#define kNumStates 12
++#define kNumLitStates 7
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++/*
++#define LZMA_STREAM_WAS_FINISHED_ID (-1)
++#define LZMA_SPEC_LEN_OFFSET (-3)
++*/
++
++Byte kLiteralNextStates[kNumStates * 2] =
++{
++ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
++ 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
++};
++
++#define LZMA_DIC_MIN (1 << 12)
++
++/* First LZMA-symbol is always decoded.
++And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
++Out:
++ Result:
++ 0 - OK
++ 1 - Error
++ p->remainLen:
++ < kMatchSpecLenStart : normal remain
++ = kMatchSpecLenStart : finished
++ = kMatchSpecLenStart + 1 : Flush marker
++ = kMatchSpecLenStart + 2 : State Init Marker
++*/
++
++static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
++{
++ CLzmaProb *probs = p->probs;
++
++ unsigned state = p->state;
++ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
++ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
++ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
++ unsigned lc = p->prop.lc;
++
++ Byte *dic = p->dic;
++ SizeT dicBufSize = p->dicBufSize;
++ SizeT dicPos = p->dicPos;
++
++ UInt32 processedPos = p->processedPos;
++ UInt32 checkDicSize = p->checkDicSize;
++ unsigned len = 0;
++
++ const Byte *buf = p->buf;
++ UInt32 range = p->range;
++ UInt32 code = p->code;
++
++ do
++ {
++ CLzmaProb *prob;
++ UInt32 bound;
++ unsigned ttt;
++ unsigned posState = processedPos & pbMask;
++
++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
++ IF_BIT_0(prob)
++ {
++ unsigned symbol;
++ UPDATE_0(prob);
++ prob = probs + Literal;
++ if (checkDicSize != 0 || processedPos != 0)
++ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
++ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
++
++ if (state < kNumLitStates)
++ {
++ symbol = 1;
++ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
++ }
++ else
++ {
++ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
++ unsigned offs = 0x100;
++ symbol = 1;
++ do
++ {
++ unsigned bit;
++ CLzmaProb *probLit;
++ matchByte <<= 1;
++ bit = (matchByte & offs);
++ probLit = prob + offs + bit + symbol;
++ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
++ }
++ while (symbol < 0x100);
++ }
++ dic[dicPos++] = (Byte)symbol;
++ processedPos++;
++
++ state = kLiteralNextStates[state];
++ /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
++ continue;
++ }
++ else
++ {
++ UPDATE_1(prob);
++ prob = probs + IsRep + state;
++ IF_BIT_0(prob)
++ {
++ UPDATE_0(prob);
++ state += kNumStates;
++ prob = probs + LenCoder;
++ }
++ else
++ {
++ UPDATE_1(prob);
++ if (checkDicSize == 0 && processedPos == 0)
++ return SZ_ERROR_DATA;
++ prob = probs + IsRepG0 + state;
++ IF_BIT_0(prob)
++ {
++ UPDATE_0(prob);
++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
++ IF_BIT_0(prob)
++ {
++ UPDATE_0(prob);
++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
++ dicPos++;
++ processedPos++;
++ state = state < kNumLitStates ? 9 : 11;
++ continue;
++ }
++ UPDATE_1(prob);
++ }
++ else
++ {
++ UInt32 distance;
++ UPDATE_1(prob);
++ prob = probs + IsRepG1 + state;
++ IF_BIT_0(prob)
++ {
++ UPDATE_0(prob);
++ distance = rep1;
++ }
++ else
++ {
++ UPDATE_1(prob);
++ prob = probs + IsRepG2 + state;
++ IF_BIT_0(prob)
++ {
++ UPDATE_0(prob);
++ distance = rep2;
++ }
++ else
++ {
++ UPDATE_1(prob);
++ distance = rep3;
++ rep3 = rep2;
++ }
++ rep2 = rep1;
++ }
++ rep1 = rep0;
++ rep0 = distance;
++ }
++ state = state < kNumLitStates ? 8 : 11;
++ prob = probs + RepLenCoder;
++ }
++ {
++ unsigned limit, offset;
++ CLzmaProb *probLen = prob + LenChoice;
++ IF_BIT_0(probLen)
++ {
++ UPDATE_0(probLen);
++ probLen = prob + LenLow + (posState << kLenNumLowBits);
++ offset = 0;
++ limit = (1 << kLenNumLowBits);
++ }
++ else
++ {
++ UPDATE_1(probLen);
++ probLen = prob + LenChoice2;
++ IF_BIT_0(probLen)
++ {
++ UPDATE_0(probLen);
++ probLen = prob + LenMid + (posState << kLenNumMidBits);
++ offset = kLenNumLowSymbols;
++ limit = (1 << kLenNumMidBits);
++ }
++ else
++ {
++ UPDATE_1(probLen);
++ probLen = prob + LenHigh;
++ offset = kLenNumLowSymbols + kLenNumMidSymbols;
++ limit = (1 << kLenNumHighBits);
++ }
++ }
++ TREE_DECODE(probLen, limit, len);
++ len += offset;
++ }
++
++ if (state >= kNumStates)
++ {
++ UInt32 distance;
++ prob = probs + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
++ TREE_6_DECODE(prob, distance);
++ if (distance >= kStartPosModelIndex)
++ {
++ unsigned posSlot = (unsigned)distance;
++ int numDirectBits = (int)(((distance >> 1) - 1));
++ distance = (2 | (distance & 1));
++ if (posSlot < kEndPosModelIndex)
++ {
++ distance <<= numDirectBits;
++ prob = probs + SpecPos + distance - posSlot - 1;
++ {
++ UInt32 mask = 1;
++ unsigned i = 1;
++ do
++ {
++ GET_BIT2(prob + i, i, ; , distance |= mask);
++ mask <<= 1;
++ }
++ while(--numDirectBits != 0);
++ }
++ }
++ else
++ {
++ numDirectBits -= kNumAlignBits;
++ do
++ {
++ NORMALIZE
++ range >>= 1;
++
++ {
++ UInt32 t;
++ code -= range;
++ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
++ distance = (distance << 1) + (t + 1);
++ code += range & t;
++ }
++ /*
++ distance <<= 1;
++ if (code >= range)
++ {
++ code -= range;
++ distance |= 1;
++ }
++ */
++ }
++ while (--numDirectBits != 0);
++ prob = probs + Align;
++ distance <<= kNumAlignBits;
++ {
++ unsigned i = 1;
++ GET_BIT2(prob + i, i, ; , distance |= 1);
++ GET_BIT2(prob + i, i, ; , distance |= 2);
++ GET_BIT2(prob + i, i, ; , distance |= 4);
++ GET_BIT2(prob + i, i, ; , distance |= 8);
++ }
++ if (distance == (UInt32)0xFFFFFFFF)
++ {
++ len += kMatchSpecLenStart;
++ state -= kNumStates;
++ break;
++ }
++ }
++ }
++ rep3 = rep2;
++ rep2 = rep1;
++ rep1 = rep0;
++ rep0 = distance + 1;
++ if (checkDicSize == 0)
++ {
++ if (distance >= processedPos)
++ return SZ_ERROR_DATA;
++ }
++ else if (distance >= checkDicSize)
++ return SZ_ERROR_DATA;
++ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
++ /* state = kLiteralNextStates[state]; */
++ }
++
++ len += kMatchMinLen;
++
++ {
++ SizeT rem = limit - dicPos;
++ unsigned curLen = ((rem < len) ? (unsigned)rem : len);
++ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
++
++ processedPos += curLen;
++
++ len -= curLen;
++ if (pos + curLen <= dicBufSize)
++ {
++ Byte *dest = dic + dicPos;
++ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
++ const Byte *lim = dest + curLen;
++ dicPos += curLen;
++ do
++ *(dest) = (Byte)*(dest + src);
++ while (++dest != lim);
++ }
++ else
++ {
++ do
++ {
++ dic[dicPos++] = dic[pos];
++ if (++pos == dicBufSize)
++ pos = 0;
++ }
++ while (--curLen != 0);
++ }
++ }
++ }
++ }
++ while (dicPos < limit && buf < bufLimit);
++ NORMALIZE;
++ p->buf = buf;
++ p->range = range;
++ p->code = code;
++ p->remainLen = len;
++ p->dicPos = dicPos;
++ p->processedPos = processedPos;
++ p->reps[0] = rep0;
++ p->reps[1] = rep1;
++ p->reps[2] = rep2;
++ p->reps[3] = rep3;
++ p->state = state;
++
++ return SZ_OK;
++}
++
++static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
++{
++ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
++ {
++ Byte *dic = p->dic;
++ SizeT dicPos = p->dicPos;
++ SizeT dicBufSize = p->dicBufSize;
++ unsigned len = p->remainLen;
++ UInt32 rep0 = p->reps[0];
++ if (limit - dicPos < len)
++ len = (unsigned)(limit - dicPos);
++
++ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
++ p->checkDicSize = p->prop.dicSize;
++
++ p->processedPos += len;
++ p->remainLen -= len;
++ while (len-- != 0)
++ {
++ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
++ dicPos++;
++ }
++ p->dicPos = dicPos;
++ }
++}
++
++/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p->needFlush and p->needInit, if required. */
++
++static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
++{
++ do
++ {
++ SizeT limit2 = limit;
++ if (p->checkDicSize == 0)
++ {
++ UInt32 rem = p->prop.dicSize - p->processedPos;
++ if (limit - p->dicPos > rem)
++ limit2 = p->dicPos + rem;
++ }
++ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
++ if (p->processedPos >= p->prop.dicSize)
++ p->checkDicSize = p->prop.dicSize;
++ LzmaDec_WriteRem(p, limit);
++ }
++ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
++
++ if (p->remainLen > kMatchSpecLenStart)
++ {
++ p->remainLen = kMatchSpecLenStart;
++ }
++ return 0;
++}
++
++typedef enum
++{
++ DUMMY_ERROR, /* unexpected end of input stream */
++ DUMMY_LIT,
++ DUMMY_MATCH,
++ DUMMY_REP
++} ELzmaDummy;
++
++static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
++{
++ UInt32 range = p->range;
++ UInt32 code = p->code;
++ const Byte *bufLimit = buf + inSize;
++ CLzmaProb *probs = p->probs;
++ unsigned state = p->state;
++ ELzmaDummy res;
++
++ {
++ CLzmaProb *prob;
++ UInt32 bound;
++ unsigned ttt;
++ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
++
++ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
++ IF_BIT_0_CHECK(prob)
++ {
++ UPDATE_0_CHECK
++
++ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
++
++ prob = probs + Literal;
++ if (p->checkDicSize != 0 || p->processedPos != 0)
++ prob += (LZMA_LIT_SIZE *
++ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
++ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
++
++ if (state < kNumLitStates)
++ {
++ unsigned symbol = 1;
++ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
++ }
++ else
++ {
++ unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
++ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
++ unsigned offs = 0x100;
++ unsigned symbol = 1;
++ do
++ {
++ unsigned bit;
++ CLzmaProb *probLit;
++ matchByte <<= 1;
++ bit = (matchByte & offs);
++ probLit = prob + offs + bit + symbol;
++ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
++ }
++ while (symbol < 0x100);
++ }
++ res = DUMMY_LIT;
++ }
++ else
++ {
++ unsigned len;
++ UPDATE_1_CHECK;
++
++ prob = probs + IsRep + state;
++ IF_BIT_0_CHECK(prob)
++ {
++ UPDATE_0_CHECK;
++ state = 0;
++ prob = probs + LenCoder;
++ res = DUMMY_MATCH;
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ res = DUMMY_REP;
++ prob = probs + IsRepG0 + state;
++ IF_BIT_0_CHECK(prob)
++ {
++ UPDATE_0_CHECK;
++ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
++ IF_BIT_0_CHECK(prob)
++ {
++ UPDATE_0_CHECK;
++ NORMALIZE_CHECK;
++ return DUMMY_REP;
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ }
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ prob = probs + IsRepG1 + state;
++ IF_BIT_0_CHECK(prob)
++ {
++ UPDATE_0_CHECK;
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ prob = probs + IsRepG2 + state;
++ IF_BIT_0_CHECK(prob)
++ {
++ UPDATE_0_CHECK;
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ }
++ }
++ }
++ state = kNumStates;
++ prob = probs + RepLenCoder;
++ }
++ {
++ unsigned limit, offset;
++ CLzmaProb *probLen = prob + LenChoice;
++ IF_BIT_0_CHECK(probLen)
++ {
++ UPDATE_0_CHECK;
++ probLen = prob + LenLow + (posState << kLenNumLowBits);
++ offset = 0;
++ limit = 1 << kLenNumLowBits;
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ probLen = prob + LenChoice2;
++ IF_BIT_0_CHECK(probLen)
++ {
++ UPDATE_0_CHECK;
++ probLen = prob + LenMid + (posState << kLenNumMidBits);
++ offset = kLenNumLowSymbols;
++ limit = 1 << kLenNumMidBits;
++ }
++ else
++ {
++ UPDATE_1_CHECK;
++ probLen = prob + LenHigh;
++ offset = kLenNumLowSymbols + kLenNumMidSymbols;
++ limit = 1 << kLenNumHighBits;
++ }
++ }
++ TREE_DECODE_CHECK(probLen, limit, len);
++ len += offset;
++ }
++
++ if (state < 4)
++ {
++ unsigned posSlot;
++ prob = probs + PosSlot +
++ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
++ kNumPosSlotBits);
++ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
++ if (posSlot >= kStartPosModelIndex)
++ {
++ int numDirectBits = ((posSlot >> 1) - 1);
++
++ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
++
++ if (posSlot < kEndPosModelIndex)
++ {
++ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
++ }
++ else
++ {
++ numDirectBits -= kNumAlignBits;
++ do
++ {
++ NORMALIZE_CHECK
++ range >>= 1;
++ code -= range & (((code - range) >> 31) - 1);
++ /* if (code >= range) code -= range; */
++ }
++ while (--numDirectBits != 0);
++ prob = probs + Align;
++ numDirectBits = kNumAlignBits;
++ }
++ {
++ unsigned i = 1;
++ do
++ {
++ GET_BIT_CHECK(prob + i, i);
++ }
++ while(--numDirectBits != 0);
++ }
++ }
++ }
++ }
++ }
++ NORMALIZE_CHECK;
++ return res;
++}
++
++
++static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
++{
++ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
++ p->range = 0xFFFFFFFF;
++ p->needFlush = 0;
++}
++
++void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
++{
++ p->needFlush = 1;
++ p->remainLen = 0;
++ p->tempBufSize = 0;
++
++ if (initDic)
++ {
++ p->processedPos = 0;
++ p->checkDicSize = 0;
++ p->needInitState = 1;
++ }
++ if (initState)
++ p->needInitState = 1;
++}
++
++void LzmaDec_Init(CLzmaDec *p)
++{
++ p->dicPos = 0;
++ LzmaDec_InitDicAndState(p, True, True);
++}
++
++static void LzmaDec_InitStateReal(CLzmaDec *p)
++{
++ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
++ UInt32 i;
++ CLzmaProb *probs = p->probs;
++ for (i = 0; i < numProbs; i++)
++ probs[i] = kBitModelTotal >> 1;
++ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
++ p->state = 0;
++ p->needInitState = 0;
++}
++
++SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
++ ELzmaFinishMode finishMode, ELzmaStatus *status)
++{
++ SizeT inSize = *srcLen;
++ (*srcLen) = 0;
++ LzmaDec_WriteRem(p, dicLimit);
++
++ *status = LZMA_STATUS_NOT_SPECIFIED;
++
++ while (p->remainLen != kMatchSpecLenStart)
++ {
++ int checkEndMarkNow;
++
++ if (p->needFlush != 0)
++ {
++ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
++ p->tempBuf[p->tempBufSize++] = *src++;
++ if (p->tempBufSize < RC_INIT_SIZE)
++ {
++ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
++ return SZ_OK;
++ }
++ if (p->tempBuf[0] != 0)
++ return SZ_ERROR_DATA;
++
++ LzmaDec_InitRc(p, p->tempBuf);
++ p->tempBufSize = 0;
++ }
++
++ checkEndMarkNow = 0;
++ if (p->dicPos >= dicLimit)
++ {
++ if (p->remainLen == 0 && p->code == 0)
++ {
++ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
++ return SZ_OK;
++ }
++ if (finishMode == LZMA_FINISH_ANY)
++ {
++ *status = LZMA_STATUS_NOT_FINISHED;
++ return SZ_OK;
++ }
++ if (p->remainLen != 0)
++ {
++ *status = LZMA_STATUS_NOT_FINISHED;
++ return SZ_ERROR_DATA;
++ }
++ checkEndMarkNow = 1;
++ }
++
++ if (p->needInitState)
++ LzmaDec_InitStateReal(p);
++
++ if (p->tempBufSize == 0)
++ {
++ SizeT processed;
++ const Byte *bufLimit;
++ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
++ {
++ int dummyRes = LzmaDec_TryDummy(p, src, inSize);
++ if (dummyRes == DUMMY_ERROR)
++ {
++ memcpy(p->tempBuf, src, inSize);
++ p->tempBufSize = (unsigned)inSize;
++ (*srcLen) += inSize;
++ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
++ return SZ_OK;
++ }
++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
++ {
++ *status = LZMA_STATUS_NOT_FINISHED;
++ return SZ_ERROR_DATA;
++ }
++ bufLimit = src;
++ }
++ else
++ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
++ p->buf = src;
++ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
++ return SZ_ERROR_DATA;
++ processed = p->buf - src;
++ (*srcLen) += processed;
++ src += processed;
++ inSize -= processed;
++ }
++ else
++ {
++ unsigned rem = p->tempBufSize, lookAhead = 0;
++ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
++ p->tempBuf[rem++] = src[lookAhead++];
++ p->tempBufSize = rem;
++ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
++ {
++ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
++ if (dummyRes == DUMMY_ERROR)
++ {
++ (*srcLen) += lookAhead;
++ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
++ return SZ_OK;
++ }
++ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
++ {
++ *status = LZMA_STATUS_NOT_FINISHED;
++ return SZ_ERROR_DATA;
++ }
++ }
++ p->buf = p->tempBuf;
++ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
++ return SZ_ERROR_DATA;
++ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
++ (*srcLen) += lookAhead;
++ src += lookAhead;
++ inSize -= lookAhead;
++ p->tempBufSize = 0;
++ }
++ }
++ if (p->code == 0)
++ *status = LZMA_STATUS_FINISHED_WITH_MARK;
++ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
++}
++
++SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
++{
++ SizeT outSize = *destLen;
++ SizeT inSize = *srcLen;
++ *srcLen = *destLen = 0;
++ for (;;)
++ {
++ SizeT inSizeCur = inSize, outSizeCur, dicPos;
++ ELzmaFinishMode curFinishMode;
++ SRes res;
++ if (p->dicPos == p->dicBufSize)
++ p->dicPos = 0;
++ dicPos = p->dicPos;
++ if (outSize > p->dicBufSize - dicPos)
++ {
++ outSizeCur = p->dicBufSize;
++ curFinishMode = LZMA_FINISH_ANY;
++ }
++ else
++ {
++ outSizeCur = dicPos + outSize;
++ curFinishMode = finishMode;
++ }
++
++ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
++ src += inSizeCur;
++ inSize -= inSizeCur;
++ *srcLen += inSizeCur;
++ outSizeCur = p->dicPos - dicPos;
++ memcpy(dest, p->dic + dicPos, outSizeCur);
++ dest += outSizeCur;
++ outSize -= outSizeCur;
++ *destLen += outSizeCur;
++ if (res != 0)
++ return res;
++ if (outSizeCur == 0 || outSize == 0)
++ return SZ_OK;
++ }
++}
++
++void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
++{
++ alloc->Free(alloc, p->probs);
++ p->probs = 0;
++}
++
++static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
++{
++ alloc->Free(alloc, p->dic);
++ p->dic = 0;
++}
++
++void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
++{
++ LzmaDec_FreeProbs(p, alloc);
++ LzmaDec_FreeDict(p, alloc);
++}
++
++SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
++{
++ UInt32 dicSize;
++ Byte d;
++
++ if (size < LZMA_PROPS_SIZE)
++ return SZ_ERROR_UNSUPPORTED;
++ else
++ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
++
++ if (dicSize < LZMA_DIC_MIN)
++ dicSize = LZMA_DIC_MIN;
++ p->dicSize = dicSize;
++
++ d = data[0];
++ if (d >= (9 * 5 * 5))
++ return SZ_ERROR_UNSUPPORTED;
++
++ p->lc = d % 9;
++ d /= 9;
++ p->pb = d / 5;
++ p->lp = d % 5;
++
++ return SZ_OK;
++}
++
++static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
++{
++ UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
++ if (p->probs == 0 || numProbs != p->numProbs)
++ {
++ LzmaDec_FreeProbs(p, alloc);
++ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
++ p->numProbs = numProbs;
++ if (p->probs == 0)
++ return SZ_ERROR_MEM;
++ }
++ return SZ_OK;
++}
++
++SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
++{
++ CLzmaProps propNew;
++ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
++ p->prop = propNew;
++ return SZ_OK;
++}
++
++SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
++{
++ CLzmaProps propNew;
++ SizeT dicBufSize;
++ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
++ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
++ dicBufSize = propNew.dicSize;
++ if (p->dic == 0 || dicBufSize != p->dicBufSize)
++ {
++ LzmaDec_FreeDict(p, alloc);
++ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
++ if (p->dic == 0)
++ {
++ LzmaDec_FreeProbs(p, alloc);
++ return SZ_ERROR_MEM;
++ }
++ }
++ p->dicBufSize = dicBufSize;
++ p->prop = propNew;
++ return SZ_OK;
++}
++
++SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
++ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
++ ELzmaStatus *status, ISzAlloc *alloc)
++{
++ CLzmaDec p;
++ SRes res;
++ SizeT inSize = *srcLen;
++ SizeT outSize = *destLen;
++ *srcLen = *destLen = 0;
++ if (inSize < RC_INIT_SIZE)
++ return SZ_ERROR_INPUT_EOF;
++
++ LzmaDec_Construct(&p);
++ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
++ if (res != 0)
++ return res;
++ p.dic = dest;
++ p.dicBufSize = outSize;
++
++ LzmaDec_Init(&p);
++
++ *srcLen = inSize;
++ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
++
++ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
++ res = SZ_ERROR_INPUT_EOF;
++
++ (*destLen) = p.dicPos;
++ LzmaDec_FreeProbs(&p, alloc);
++ return res;
++}
+--- /dev/null
++++ b/lzma/LzmaEnc.c
+@@ -0,0 +1,2335 @@
++/* LzmaEnc.c -- LZMA Encoder
++2008-04-28
++Copyright (c) 1999-2008 Igor Pavlov
++Read LzmaEnc.h for license options */
++
++#if defined(SHOW_STAT) || defined(SHOW_STAT2)
++#include <stdio.h>
++#endif
++
++#include <string.h>
++
++#include "LzmaEnc.h"
++
++#include "LzFind.h"
++#ifdef COMPRESS_MF_MT
++#include "LzFindMt.h"
++#endif
++
++/* #define SHOW_STAT */
++/* #define SHOW_STAT2 */
++
++#ifdef SHOW_STAT
++static int ttt = 0;
++#endif
++
++#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
++
++#define kBlockSize (9 << 10)
++#define kUnpackBlockSize (1 << 18)
++#define kMatchArraySize (1 << 21)
++#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
++
++#define kNumMaxDirectBits (31)
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++#define kProbInitValue (kBitModelTotal >> 1)
++
++#define kNumMoveReducingBits 4
++#define kNumBitPriceShiftBits 4
++#define kBitPrice (1 << kNumBitPriceShiftBits)
++
++void LzmaEncProps_Init(CLzmaEncProps *p)
++{
++ p->level = 5;
++ p->dictSize = p->mc = 0;
++ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
++ p->writeEndMark = 0;
++}
++
++void LzmaEncProps_Normalize(CLzmaEncProps *p)
++{
++ int level = p->level;
++ if (level < 0) level = 5;
++ p->level = level;
++ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
++ if (p->lc < 0) p->lc = 3;
++ if (p->lp < 0) p->lp = 0;
++ if (p->pb < 0) p->pb = 2;
++ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
++ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
++ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
++ if (p->numHashBytes < 0) p->numHashBytes = 4;
++ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
++ if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1);
++}
++
++UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
++{
++ CLzmaEncProps props = *props2;
++ LzmaEncProps_Normalize(&props);
++ return props.dictSize;
++}
++
++/* #define LZMA_LOG_BSR */
++/* Define it for Intel's CPU */
++
++
++#ifdef LZMA_LOG_BSR
++
++#define kDicLogSizeMaxCompress 30
++
++#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
++
++UInt32 GetPosSlot1(UInt32 pos)
++{
++ UInt32 res;
++ BSR2_RET(pos, res);
++ return res;
++}
++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
++#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
++
++#else
++
++#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
++#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
++
++void LzmaEnc_FastPosInit(Byte *g_FastPos)
++{
++ int c = 2, slotFast;
++ g_FastPos[0] = 0;
++ g_FastPos[1] = 1;
++
++ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
++ {
++ UInt32 k = (1 << ((slotFast >> 1) - 1));
++ UInt32 j;
++ for (j = 0; j < k; j++, c++)
++ g_FastPos[c] = (Byte)slotFast;
++ }
++}
++
++#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
++ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
++ res = p->g_FastPos[pos >> i] + (i * 2); }
++/*
++#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
++ p->g_FastPos[pos >> 6] + 12 : \
++ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
++*/
++
++#define GetPosSlot1(pos) p->g_FastPos[pos]
++#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
++#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
++
++#endif
++
++
++#define LZMA_NUM_REPS 4
++
++typedef unsigned CState;
++
++typedef struct _COptimal
++{
++ UInt32 price;
++
++ CState state;
++ int prev1IsChar;
++ int prev2;
++
++ UInt32 posPrev2;
++ UInt32 backPrev2;
++
++ UInt32 posPrev;
++ UInt32 backPrev;
++ UInt32 backs[LZMA_NUM_REPS];
++} COptimal;
++
++#define kNumOpts (1 << 12)
++
++#define kNumLenToPosStates 4
++#define kNumPosSlotBits 6
++#define kDicLogSizeMin 0
++#define kDicLogSizeMax 32
++#define kDistTableSizeMax (kDicLogSizeMax * 2)
++
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++#define kAlignMask (kAlignTableSize - 1)
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
++
++#define kNumFullDistances (1 << (kEndPosModelIndex / 2))
++
++#ifdef _LZMA_PROB32
++#define CLzmaProb UInt32
++#else
++#define CLzmaProb UInt16
++#endif
++
++#define LZMA_PB_MAX 4
++#define LZMA_LC_MAX 8
++#define LZMA_LP_MAX 4
++
++#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
++
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
++
++#define LZMA_MATCH_LEN_MIN 2
++#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
++
++#define kNumStates 12
++
++typedef struct
++{
++ CLzmaProb choice;
++ CLzmaProb choice2;
++ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
++ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
++ CLzmaProb high[kLenNumHighSymbols];
++} CLenEnc;
++
++typedef struct
++{
++ CLenEnc p;
++ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
++ UInt32 tableSize;
++ UInt32 counters[LZMA_NUM_PB_STATES_MAX];
++} CLenPriceEnc;
++
++typedef struct _CRangeEnc
++{
++ UInt32 range;
++ Byte cache;
++ UInt64 low;
++ UInt64 cacheSize;
++ Byte *buf;
++ Byte *bufLim;
++ Byte *bufBase;
++ ISeqOutStream *outStream;
++ UInt64 processed;
++ SRes res;
++} CRangeEnc;
++
++typedef struct _CSeqInStreamBuf
++{
++ ISeqInStream funcTable;
++ const Byte *data;
++ SizeT rem;
++} CSeqInStreamBuf;
++
++static SRes MyRead(void *pp, void *data, size_t *size)
++{
++ size_t curSize = *size;
++ CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
++ if (p->rem < curSize)
++ curSize = p->rem;
++ memcpy(data, p->data, curSize);
++ p->rem -= curSize;
++ p->data += curSize;
++ *size = curSize;
++ return SZ_OK;
++}
++
++typedef struct
++{
++ CLzmaProb *litProbs;
++
++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
++ CLzmaProb isRep[kNumStates];
++ CLzmaProb isRepG0[kNumStates];
++ CLzmaProb isRepG1[kNumStates];
++ CLzmaProb isRepG2[kNumStates];
++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
++
++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
++ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
++
++ CLenPriceEnc lenEnc;
++ CLenPriceEnc repLenEnc;
++
++ UInt32 reps[LZMA_NUM_REPS];
++ UInt32 state;
++} CSaveState;
++
++typedef struct _CLzmaEnc
++{
++ IMatchFinder matchFinder;
++ void *matchFinderObj;
++
++ #ifdef COMPRESS_MF_MT
++ Bool mtMode;
++ CMatchFinderMt matchFinderMt;
++ #endif
++
++ CMatchFinder matchFinderBase;
++
++ #ifdef COMPRESS_MF_MT
++ Byte pad[128];
++ #endif
++
++ UInt32 optimumEndIndex;
++ UInt32 optimumCurrentIndex;
++
++ Bool longestMatchWasFound;
++ UInt32 longestMatchLength;
++ UInt32 numDistancePairs;
++
++ COptimal opt[kNumOpts];
++
++ #ifndef LZMA_LOG_BSR
++ Byte g_FastPos[1 << kNumLogBits];
++ #endif
++
++ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
++ UInt32 matchDistances[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
++ UInt32 numFastBytes;
++ UInt32 additionalOffset;
++ UInt32 reps[LZMA_NUM_REPS];
++ UInt32 state;
++
++ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
++ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
++ UInt32 alignPrices[kAlignTableSize];
++ UInt32 alignPriceCount;
++
++ UInt32 distTableSize;
++
++ unsigned lc, lp, pb;
++ unsigned lpMask, pbMask;
++
++ CLzmaProb *litProbs;
++
++ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
++ CLzmaProb isRep[kNumStates];
++ CLzmaProb isRepG0[kNumStates];
++ CLzmaProb isRepG1[kNumStates];
++ CLzmaProb isRepG2[kNumStates];
++ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
++
++ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
++ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
++ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
++
++ CLenPriceEnc lenEnc;
++ CLenPriceEnc repLenEnc;
++
++ unsigned lclp;
++
++ Bool fastMode;
++
++ CRangeEnc rc;
++
++ Bool writeEndMark;
++ UInt64 nowPos64;
++ UInt32 matchPriceCount;
++ Bool finished;
++ Bool multiThread;
++
++ SRes result;
++ UInt32 dictSize;
++ UInt32 matchFinderCycles;
++
++ ISeqInStream *inStream;
++ CSeqInStreamBuf seqBufInStream;
++
++ CSaveState saveState;
++} CLzmaEnc;
++
++void LzmaEnc_SaveState(CLzmaEncHandle pp)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ CSaveState *dest = &p->saveState;
++ int i;
++ dest->lenEnc = p->lenEnc;
++ dest->repLenEnc = p->repLenEnc;
++ dest->state = p->state;
++
++ for (i = 0; i < kNumStates; i++)
++ {
++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
++ }
++ for (i = 0; i < kNumLenToPosStates; i++)
++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
++ memcpy(dest->reps, p->reps, sizeof(p->reps));
++ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
++}
++
++void LzmaEnc_RestoreState(CLzmaEncHandle pp)
++{
++ CLzmaEnc *dest = (CLzmaEnc *)pp;
++ const CSaveState *p = &dest->saveState;
++ int i;
++ dest->lenEnc = p->lenEnc;
++ dest->repLenEnc = p->repLenEnc;
++ dest->state = p->state;
++
++ for (i = 0; i < kNumStates; i++)
++ {
++ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
++ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
++ }
++ for (i = 0; i < kNumLenToPosStates; i++)
++ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
++ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
++ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
++ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
++ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
++ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
++ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
++ memcpy(dest->reps, p->reps, sizeof(p->reps));
++ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
++}
++
++SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ CLzmaEncProps props = *props2;
++ LzmaEncProps_Normalize(&props);
++
++ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
++ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
++ return SZ_ERROR_PARAM;
++ p->dictSize = props.dictSize;
++ p->matchFinderCycles = props.mc;
++ {
++ unsigned fb = props.fb;
++ if (fb < 5)
++ fb = 5;
++ if (fb > LZMA_MATCH_LEN_MAX)
++ fb = LZMA_MATCH_LEN_MAX;
++ p->numFastBytes = fb;
++ }
++ p->lc = props.lc;
++ p->lp = props.lp;
++ p->pb = props.pb;
++ p->fastMode = (props.algo == 0);
++ p->matchFinderBase.btMode = props.btMode;
++ {
++ UInt32 numHashBytes = 4;
++ if (props.btMode)
++ {
++ if (props.numHashBytes < 2)
++ numHashBytes = 2;
++ else if (props.numHashBytes < 4)
++ numHashBytes = props.numHashBytes;
++ }
++ p->matchFinderBase.numHashBytes = numHashBytes;
++ }
++
++ p->matchFinderBase.cutValue = props.mc;
++
++ p->writeEndMark = props.writeEndMark;
++
++ #ifdef COMPRESS_MF_MT
++ /*
++ if (newMultiThread != _multiThread)
++ {
++ ReleaseMatchFinder();
++ _multiThread = newMultiThread;
++ }
++ */
++ p->multiThread = (props.numThreads > 1);
++ #endif
++
++ return SZ_OK;
++}
++
++static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
++static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
++static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
++static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
++
++/*
++ void UpdateChar() { Index = kLiteralNextStates[Index]; }
++ void UpdateMatch() { Index = kMatchNextStates[Index]; }
++ void UpdateRep() { Index = kRepNextStates[Index]; }
++ void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
++*/
++
++#define IsCharState(s) ((s) < 7)
++
++
++#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
++
++#define kInfinityPrice (1 << 30)
++
++static void RangeEnc_Construct(CRangeEnc *p)
++{
++ p->outStream = 0;
++ p->bufBase = 0;
++}
++
++#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
++
++#define RC_BUF_SIZE (1 << 16)
++static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
++{
++ if (p->bufBase == 0)
++ {
++ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
++ if (p->bufBase == 0)
++ return 0;
++ p->bufLim = p->bufBase + RC_BUF_SIZE;
++ }
++ return 1;
++}
++
++static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
++{
++ alloc->Free(alloc, p->bufBase);
++ p->bufBase = 0;
++}
++
++static void RangeEnc_Init(CRangeEnc *p)
++{
++ /* Stream.Init(); */
++ p->low = 0;
++ p->range = 0xFFFFFFFF;
++ p->cacheSize = 1;
++ p->cache = 0;
++
++ p->buf = p->bufBase;
++
++ p->processed = 0;
++ p->res = SZ_OK;
++}
++
++static void RangeEnc_FlushStream(CRangeEnc *p)
++{
++ size_t num;
++ if (p->res != SZ_OK)
++ return;
++ num = p->buf - p->bufBase;
++ if (num != p->outStream->Write(p->outStream, p->bufBase, num))
++ p->res = SZ_ERROR_WRITE;
++ p->processed += num;
++ p->buf = p->bufBase;
++}
++
++static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
++{
++ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
++ {
++ Byte temp = p->cache;
++ do
++ {
++ Byte *buf = p->buf;
++ *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
++ p->buf = buf;
++ if (buf == p->bufLim)
++ RangeEnc_FlushStream(p);
++ temp = 0xFF;
++ }
++ while (--p->cacheSize != 0);
++ p->cache = (Byte)((UInt32)p->low >> 24);
++ }
++ p->cacheSize++;
++ p->low = (UInt32)p->low << 8;
++}
++
++static void RangeEnc_FlushData(CRangeEnc *p)
++{
++ int i;
++ for (i = 0; i < 5; i++)
++ RangeEnc_ShiftLow(p);
++}
++
++static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
++{
++ do
++ {
++ p->range >>= 1;
++ p->low += p->range & (0 - ((value >> --numBits) & 1));
++ if (p->range < kTopValue)
++ {
++ p->range <<= 8;
++ RangeEnc_ShiftLow(p);
++ }
++ }
++ while (numBits != 0);
++}
++
++static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
++{
++ UInt32 ttt = *prob;
++ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
++ if (symbol == 0)
++ {
++ p->range = newBound;
++ ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
++ }
++ else
++ {
++ p->low += newBound;
++ p->range -= newBound;
++ ttt -= ttt >> kNumMoveBits;
++ }
++ *prob = (CLzmaProb)ttt;
++ if (p->range < kTopValue)
++ {
++ p->range <<= 8;
++ RangeEnc_ShiftLow(p);
++ }
++}
++
++static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
++{
++ symbol |= 0x100;
++ do
++ {
++ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
++ symbol <<= 1;
++ }
++ while (symbol < 0x10000);
++}
++
++static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
++{
++ UInt32 offs = 0x100;
++ symbol |= 0x100;
++ do
++ {
++ matchByte <<= 1;
++ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
++ symbol <<= 1;
++ offs &= ~(matchByte ^ symbol);
++ }
++ while (symbol < 0x10000);
++}
++
++void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
++{
++ UInt32 i;
++ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
++ {
++ const int kCyclesBits = kNumBitPriceShiftBits;
++ UInt32 w = i;
++ UInt32 bitCount = 0;
++ int j;
++ for (j = 0; j < kCyclesBits; j++)
++ {
++ w = w * w;
++ bitCount <<= 1;
++ while (w >= ((UInt32)1 << 16))
++ {
++ w >>= 1;
++ bitCount++;
++ }
++ }
++ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
++ }
++}
++
++
++#define GET_PRICE(prob, symbol) \
++ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
++
++#define GET_PRICEa(prob, symbol) \
++ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
++
++#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
++#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
++
++#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
++#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
++
++static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
++{
++ UInt32 price = 0;
++ symbol |= 0x100;
++ do
++ {
++ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
++ symbol <<= 1;
++ }
++ while (symbol < 0x10000);
++ return price;
++};
++
++static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
++{
++ UInt32 price = 0;
++ UInt32 offs = 0x100;
++ symbol |= 0x100;
++ do
++ {
++ matchByte <<= 1;
++ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
++ symbol <<= 1;
++ offs &= ~(matchByte ^ symbol);
++ }
++ while (symbol < 0x10000);
++ return price;
++};
++
++
++static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
++{
++ UInt32 m = 1;
++ int i;
++ for (i = numBitLevels; i != 0 ;)
++ {
++ UInt32 bit;
++ i--;
++ bit = (symbol >> i) & 1;
++ RangeEnc_EncodeBit(rc, probs + m, bit);
++ m = (m << 1) | bit;
++ }
++};
++
++static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
++{
++ UInt32 m = 1;
++ int i;
++ for (i = 0; i < numBitLevels; i++)
++ {
++ UInt32 bit = symbol & 1;
++ RangeEnc_EncodeBit(rc, probs + m, bit);
++ m = (m << 1) | bit;
++ symbol >>= 1;
++ }
++}
++
++static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
++{
++ UInt32 price = 0;
++ symbol |= (1 << numBitLevels);
++ while (symbol != 1)
++ {
++ price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
++ symbol >>= 1;
++ }
++ return price;
++}
++
++static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
++{
++ UInt32 price = 0;
++ UInt32 m = 1;
++ int i;
++ for (i = numBitLevels; i != 0; i--)
++ {
++ UInt32 bit = symbol & 1;
++ symbol >>= 1;
++ price += GET_PRICEa(probs[m], bit);
++ m = (m << 1) | bit;
++ }
++ return price;
++}
++
++
++static void LenEnc_Init(CLenEnc *p)
++{
++ unsigned i;
++ p->choice = p->choice2 = kProbInitValue;
++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
++ p->low[i] = kProbInitValue;
++ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
++ p->mid[i] = kProbInitValue;
++ for (i = 0; i < kLenNumHighSymbols; i++)
++ p->high[i] = kProbInitValue;
++}
++
++static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
++{
++ if (symbol < kLenNumLowSymbols)
++ {
++ RangeEnc_EncodeBit(rc, &p->choice, 0);
++ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
++ }
++ else
++ {
++ RangeEnc_EncodeBit(rc, &p->choice, 1);
++ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
++ {
++ RangeEnc_EncodeBit(rc, &p->choice2, 0);
++ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
++ }
++ else
++ {
++ RangeEnc_EncodeBit(rc, &p->choice2, 1);
++ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
++ }
++ }
++}
++
++static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
++{
++ UInt32 a0 = GET_PRICE_0a(p->choice);
++ UInt32 a1 = GET_PRICE_1a(p->choice);
++ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
++ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
++ UInt32 i = 0;
++ for (i = 0; i < kLenNumLowSymbols; i++)
++ {
++ if (i >= numSymbols)
++ return;
++ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
++ }
++ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
++ {
++ if (i >= numSymbols)
++ return;
++ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
++ }
++ for (; i < numSymbols; i++)
++ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
++}
++
++static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
++{
++ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
++ p->counters[posState] = p->tableSize;
++}
++
++static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
++{
++ UInt32 posState;
++ for (posState = 0; posState < numPosStates; posState++)
++ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
++}
++
++static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
++{
++ LenEnc_Encode(&p->p, rc, symbol, posState);
++ if (updatePrice)
++ if (--p->counters[posState] == 0)
++ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
++}
++
++
++
++
++static void MovePos(CLzmaEnc *p, UInt32 num)
++{
++ #ifdef SHOW_STAT
++ ttt += num;
++ printf("\n MovePos %d", num);
++ #endif
++ if (num != 0)
++ {
++ p->additionalOffset += num;
++ p->matchFinder.Skip(p->matchFinderObj, num);
++ }
++}
++
++static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
++{
++ UInt32 lenRes = 0, numDistancePairs;
++ numDistancePairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matchDistances);
++ #ifdef SHOW_STAT
++ printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2);
++ if (ttt >= 61994)
++ ttt = ttt;
++
++ ttt++;
++ {
++ UInt32 i;
++ for (i = 0; i < numDistancePairs; i += 2)
++ printf("%2d %6d | ", p->matchDistances[i], p->matchDistances[i + 1]);
++ }
++ #endif
++ if (numDistancePairs > 0)
++ {
++ lenRes = p->matchDistances[numDistancePairs - 2];
++ if (lenRes == p->numFastBytes)
++ {
++ UInt32 numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) + 1;
++ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
++ UInt32 distance = p->matchDistances[numDistancePairs - 1] + 1;
++ if (numAvail > LZMA_MATCH_LEN_MAX)
++ numAvail = LZMA_MATCH_LEN_MAX;
++
++ {
++ const Byte *pby2 = pby - distance;
++ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
++ }
++ }
++ }
++ p->additionalOffset++;
++ *numDistancePairsRes = numDistancePairs;
++ return lenRes;
++}
++
++
++#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
++#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
++#define IsShortRep(p) ((p)->backPrev == 0)
++
++static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
++{
++ return
++ GET_PRICE_0(p->isRepG0[state]) +
++ GET_PRICE_0(p->isRep0Long[state][posState]);
++}
++
++static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
++{
++ UInt32 price;
++ if (repIndex == 0)
++ {
++ price = GET_PRICE_0(p->isRepG0[state]);
++ price += GET_PRICE_1(p->isRep0Long[state][posState]);
++ }
++ else
++ {
++ price = GET_PRICE_1(p->isRepG0[state]);
++ if (repIndex == 1)
++ price += GET_PRICE_0(p->isRepG1[state]);
++ else
++ {
++ price += GET_PRICE_1(p->isRepG1[state]);
++ price += GET_PRICE(p->isRepG2[state], repIndex - 2);
++ }
++ }
++ return price;
++}
++
++static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
++{
++ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
++ GetPureRepPrice(p, repIndex, state, posState);
++}
++
++static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
++{
++ UInt32 posMem = p->opt[cur].posPrev;
++ UInt32 backMem = p->opt[cur].backPrev;
++ p->optimumEndIndex = cur;
++ do
++ {
++ if (p->opt[cur].prev1IsChar)
++ {
++ MakeAsChar(&p->opt[posMem])
++ p->opt[posMem].posPrev = posMem - 1;
++ if (p->opt[cur].prev2)
++ {
++ p->opt[posMem - 1].prev1IsChar = False;
++ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
++ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
++ }
++ }
++ {
++ UInt32 posPrev = posMem;
++ UInt32 backCur = backMem;
++
++ backMem = p->opt[posPrev].backPrev;
++ posMem = p->opt[posPrev].posPrev;
++
++ p->opt[posPrev].backPrev = backCur;
++ p->opt[posPrev].posPrev = cur;
++ cur = posPrev;
++ }
++ }
++ while (cur != 0);
++ *backRes = p->opt[0].backPrev;
++ p->optimumCurrentIndex = p->opt[0].posPrev;
++ return p->optimumCurrentIndex;
++}
++
++#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
++
++static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
++{
++ UInt32 numAvailableBytes, lenMain, numDistancePairs;
++ const Byte *data;
++ UInt32 reps[LZMA_NUM_REPS];
++ UInt32 repLens[LZMA_NUM_REPS];
++ UInt32 repMaxIndex, i;
++ UInt32 *matchDistances;
++ Byte currentByte, matchByte;
++ UInt32 posState;
++ UInt32 matchPrice, repMatchPrice;
++ UInt32 lenEnd;
++ UInt32 len;
++ UInt32 normalMatchPrice;
++ UInt32 cur;
++ if (p->optimumEndIndex != p->optimumCurrentIndex)
++ {
++ const COptimal *opt = &p->opt[p->optimumCurrentIndex];
++ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
++ *backRes = opt->backPrev;
++ p->optimumCurrentIndex = opt->posPrev;
++ return lenRes;
++ }
++ p->optimumCurrentIndex = p->optimumEndIndex = 0;
++
++ numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
++
++ if (!p->longestMatchWasFound)
++ {
++ lenMain = ReadMatchDistances(p, &numDistancePairs);
++ }
++ else
++ {
++ lenMain = p->longestMatchLength;
++ numDistancePairs = p->numDistancePairs;
++ p->longestMatchWasFound = False;
++ }
++
++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
++ if (numAvailableBytes < 2)
++ {
++ *backRes = (UInt32)(-1);
++ return 1;
++ }
++ if (numAvailableBytes > LZMA_MATCH_LEN_MAX)
++ numAvailableBytes = LZMA_MATCH_LEN_MAX;
++
++ repMaxIndex = 0;
++ for (i = 0; i < LZMA_NUM_REPS; i++)
++ {
++ UInt32 lenTest;
++ const Byte *data2;
++ reps[i] = p->reps[i];
++ data2 = data - (reps[i] + 1);
++ if (data[0] != data2[0] || data[1] != data2[1])
++ {
++ repLens[i] = 0;
++ continue;
++ }
++ for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
++ repLens[i] = lenTest;
++ if (lenTest > repLens[repMaxIndex])
++ repMaxIndex = i;
++ }
++ if (repLens[repMaxIndex] >= p->numFastBytes)
++ {
++ UInt32 lenRes;
++ *backRes = repMaxIndex;
++ lenRes = repLens[repMaxIndex];
++ MovePos(p, lenRes - 1);
++ return lenRes;
++ }
++
++ matchDistances = p->matchDistances;
++ if (lenMain >= p->numFastBytes)
++ {
++ *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS;
++ MovePos(p, lenMain - 1);
++ return lenMain;
++ }
++ currentByte = *data;
++ matchByte = *(data - (reps[0] + 1));
++
++ if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
++ {
++ *backRes = (UInt32)-1;
++ return 1;
++ }
++
++ p->opt[0].state = (CState)p->state;
++
++ posState = (position & p->pbMask);
++
++ {
++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
++ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
++ (!IsCharState(p->state) ?
++ LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) :
++ LitEnc_GetPrice(probs, currentByte, p->ProbPrices));
++ }
++
++ MakeAsChar(&p->opt[1]);
++
++ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
++
++ if (matchByte == currentByte)
++ {
++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
++ if (shortRepPrice < p->opt[1].price)
++ {
++ p->opt[1].price = shortRepPrice;
++ MakeAsShortRep(&p->opt[1]);
++ }
++ }
++ lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
++
++ if (lenEnd < 2)
++ {
++ *backRes = p->opt[1].backPrev;
++ return 1;
++ }
++
++ p->opt[1].posPrev = 0;
++ for (i = 0; i < LZMA_NUM_REPS; i++)
++ p->opt[0].backs[i] = reps[i];
++
++ len = lenEnd;
++ do
++ p->opt[len--].price = kInfinityPrice;
++ while (len >= 2);
++
++ for (i = 0; i < LZMA_NUM_REPS; i++)
++ {
++ UInt32 repLen = repLens[i];
++ UInt32 price;
++ if (repLen < 2)
++ continue;
++ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
++ do
++ {
++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
++ COptimal *opt = &p->opt[repLen];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = 0;
++ opt->backPrev = i;
++ opt->prev1IsChar = False;
++ }
++ }
++ while (--repLen >= 2);
++ }
++
++ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
++
++ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
++ if (len <= lenMain)
++ {
++ UInt32 offs = 0;
++ while (len > matchDistances[offs])
++ offs += 2;
++ for (; ; len++)
++ {
++ COptimal *opt;
++ UInt32 distance = matchDistances[offs + 1];
++
++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
++ UInt32 lenToPosState = GetLenToPosState(len);
++ if (distance < kNumFullDistances)
++ curAndLenPrice += p->distancesPrices[lenToPosState][distance];
++ else
++ {
++ UInt32 slot;
++ GetPosSlot2(distance, slot);
++ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
++ }
++ opt = &p->opt[len];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = 0;
++ opt->backPrev = distance + LZMA_NUM_REPS;
++ opt->prev1IsChar = False;
++ }
++ if (len == matchDistances[offs])
++ {
++ offs += 2;
++ if (offs == numDistancePairs)
++ break;
++ }
++ }
++ }
++
++ cur = 0;
++
++ #ifdef SHOW_STAT2
++ if (position >= 0)
++ {
++ unsigned i;
++ printf("\n pos = %4X", position);
++ for (i = cur; i <= lenEnd; i++)
++ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
++ }
++ #endif
++
++ for (;;)
++ {
++ UInt32 numAvailableBytesFull, newLen, numDistancePairs;
++ COptimal *curOpt;
++ UInt32 posPrev;
++ UInt32 state;
++ UInt32 curPrice;
++ Bool nextIsChar;
++ const Byte *data;
++ Byte currentByte, matchByte;
++ UInt32 posState;
++ UInt32 curAnd1Price;
++ COptimal *nextOpt;
++ UInt32 matchPrice, repMatchPrice;
++ UInt32 numAvailableBytes;
++ UInt32 startLen;
++
++ cur++;
++ if (cur == lenEnd)
++ return Backward(p, backRes, cur);
++
++ numAvailableBytesFull = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
++ newLen = ReadMatchDistances(p, &numDistancePairs);
++ if (newLen >= p->numFastBytes)
++ {
++ p->numDistancePairs = numDistancePairs;
++ p->longestMatchLength = newLen;
++ p->longestMatchWasFound = True;
++ return Backward(p, backRes, cur);
++ }
++ position++;
++ curOpt = &p->opt[cur];
++ posPrev = curOpt->posPrev;
++ if (curOpt->prev1IsChar)
++ {
++ posPrev--;
++ if (curOpt->prev2)
++ {
++ state = p->opt[curOpt->posPrev2].state;
++ if (curOpt->backPrev2 < LZMA_NUM_REPS)
++ state = kRepNextStates[state];
++ else
++ state = kMatchNextStates[state];
++ }
++ else
++ state = p->opt[posPrev].state;
++ state = kLiteralNextStates[state];
++ }
++ else
++ state = p->opt[posPrev].state;
++ if (posPrev == cur - 1)
++ {
++ if (IsShortRep(curOpt))
++ state = kShortRepNextStates[state];
++ else
++ state = kLiteralNextStates[state];
++ }
++ else
++ {
++ UInt32 pos;
++ const COptimal *prevOpt;
++ if (curOpt->prev1IsChar && curOpt->prev2)
++ {
++ posPrev = curOpt->posPrev2;
++ pos = curOpt->backPrev2;
++ state = kRepNextStates[state];
++ }
++ else
++ {
++ pos = curOpt->backPrev;
++ if (pos < LZMA_NUM_REPS)
++ state = kRepNextStates[state];
++ else
++ state = kMatchNextStates[state];
++ }
++ prevOpt = &p->opt[posPrev];
++ if (pos < LZMA_NUM_REPS)
++ {
++ UInt32 i;
++ reps[0] = prevOpt->backs[pos];
++ for (i = 1; i <= pos; i++)
++ reps[i] = prevOpt->backs[i - 1];
++ for (; i < LZMA_NUM_REPS; i++)
++ reps[i] = prevOpt->backs[i];
++ }
++ else
++ {
++ UInt32 i;
++ reps[0] = (pos - LZMA_NUM_REPS);
++ for (i = 1; i < LZMA_NUM_REPS; i++)
++ reps[i] = prevOpt->backs[i - 1];
++ }
++ }
++ curOpt->state = (CState)state;
++
++ curOpt->backs[0] = reps[0];
++ curOpt->backs[1] = reps[1];
++ curOpt->backs[2] = reps[2];
++ curOpt->backs[3] = reps[3];
++
++ curPrice = curOpt->price;
++ nextIsChar = False;
++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
++ currentByte = *data;
++ matchByte = *(data - (reps[0] + 1));
++
++ posState = (position & p->pbMask);
++
++ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
++ {
++ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
++ curAnd1Price +=
++ (!IsCharState(state) ?
++ LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) :
++ LitEnc_GetPrice(probs, currentByte, p->ProbPrices));
++ }
++
++ nextOpt = &p->opt[cur + 1];
++
++ if (curAnd1Price < nextOpt->price)
++ {
++ nextOpt->price = curAnd1Price;
++ nextOpt->posPrev = cur;
++ MakeAsChar(nextOpt);
++ nextIsChar = True;
++ }
++
++ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
++ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
++
++ if (matchByte == currentByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
++ {
++ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
++ if (shortRepPrice <= nextOpt->price)
++ {
++ nextOpt->price = shortRepPrice;
++ nextOpt->posPrev = cur;
++ MakeAsShortRep(nextOpt);
++ nextIsChar = True;
++ }
++ }
++
++ {
++ UInt32 temp = kNumOpts - 1 - cur;
++ if (temp < numAvailableBytesFull)
++ numAvailableBytesFull = temp;
++ }
++ numAvailableBytes = numAvailableBytesFull;
++
++ if (numAvailableBytes < 2)
++ continue;
++ if (numAvailableBytes > p->numFastBytes)
++ numAvailableBytes = p->numFastBytes;
++ if (!nextIsChar && matchByte != currentByte) /* speed optimization */
++ {
++ /* try Literal + rep0 */
++ UInt32 temp;
++ UInt32 lenTest2;
++ const Byte *data2 = data - (reps[0] + 1);
++ UInt32 limit = p->numFastBytes + 1;
++ if (limit > numAvailableBytesFull)
++ limit = numAvailableBytesFull;
++
++ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
++ lenTest2 = temp - 1;
++ if (lenTest2 >= 2)
++ {
++ UInt32 state2 = kLiteralNextStates[state];
++ UInt32 posStateNext = (position + 1) & p->pbMask;
++ UInt32 nextRepMatchPrice = curAnd1Price +
++ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
++ GET_PRICE_1(p->isRep[state2]);
++ /* for (; lenTest2 >= 2; lenTest2--) */
++ {
++ UInt32 curAndLenPrice;
++ COptimal *opt;
++ UInt32 offset = cur + 1 + lenTest2;
++ while (lenEnd < offset)
++ p->opt[++lenEnd].price = kInfinityPrice;
++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
++ opt = &p->opt[offset];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = cur + 1;
++ opt->backPrev = 0;
++ opt->prev1IsChar = True;
++ opt->prev2 = False;
++ }
++ }
++ }
++ }
++
++ startLen = 2; /* speed optimization */
++ {
++ UInt32 repIndex;
++ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
++ {
++ UInt32 lenTest;
++ UInt32 lenTestTemp;
++ UInt32 price;
++ const Byte *data2 = data - (reps[repIndex] + 1);
++ if (data[0] != data2[0] || data[1] != data2[1])
++ continue;
++ for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
++ while (lenEnd < cur + lenTest)
++ p->opt[++lenEnd].price = kInfinityPrice;
++ lenTestTemp = lenTest;
++ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
++ do
++ {
++ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
++ COptimal *opt = &p->opt[cur + lenTest];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = cur;
++ opt->backPrev = repIndex;
++ opt->prev1IsChar = False;
++ }
++ }
++ while (--lenTest >= 2);
++ lenTest = lenTestTemp;
++
++ if (repIndex == 0)
++ startLen = lenTest + 1;
++
++ /* if (_maxMode) */
++ {
++ UInt32 lenTest2 = lenTest + 1;
++ UInt32 limit = lenTest2 + p->numFastBytes;
++ UInt32 nextRepMatchPrice;
++ if (limit > numAvailableBytesFull)
++ limit = numAvailableBytesFull;
++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
++ lenTest2 -= lenTest + 1;
++ if (lenTest2 >= 2)
++ {
++ UInt32 state2 = kRepNextStates[state];
++ UInt32 posStateNext = (position + lenTest) & p->pbMask;
++ UInt32 curAndLenCharPrice =
++ price + p->repLenEnc.prices[posState][lenTest - 2] +
++ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
++ data[lenTest], data2[lenTest], p->ProbPrices);
++ state2 = kLiteralNextStates[state2];
++ posStateNext = (position + lenTest + 1) & p->pbMask;
++ nextRepMatchPrice = curAndLenCharPrice +
++ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
++ GET_PRICE_1(p->isRep[state2]);
++
++ /* for (; lenTest2 >= 2; lenTest2--) */
++ {
++ UInt32 curAndLenPrice;
++ COptimal *opt;
++ UInt32 offset = cur + lenTest + 1 + lenTest2;
++ while (lenEnd < offset)
++ p->opt[++lenEnd].price = kInfinityPrice;
++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
++ opt = &p->opt[offset];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = cur + lenTest + 1;
++ opt->backPrev = 0;
++ opt->prev1IsChar = True;
++ opt->prev2 = True;
++ opt->posPrev2 = cur;
++ opt->backPrev2 = repIndex;
++ }
++ }
++ }
++ }
++ }
++ }
++ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
++ if (newLen > numAvailableBytes)
++ {
++ newLen = numAvailableBytes;
++ for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
++ matchDistances[numDistancePairs] = newLen;
++ numDistancePairs += 2;
++ }
++ if (newLen >= startLen)
++ {
++ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
++ UInt32 offs, curBack, posSlot;
++ UInt32 lenTest;
++ while (lenEnd < cur + newLen)
++ p->opt[++lenEnd].price = kInfinityPrice;
++
++ offs = 0;
++ while (startLen > matchDistances[offs])
++ offs += 2;
++ curBack = matchDistances[offs + 1];
++ GetPosSlot2(curBack, posSlot);
++ for (lenTest = /*2*/ startLen; ; lenTest++)
++ {
++ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
++ UInt32 lenToPosState = GetLenToPosState(lenTest);
++ COptimal *opt;
++ if (curBack < kNumFullDistances)
++ curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
++ else
++ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
++
++ opt = &p->opt[cur + lenTest];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = cur;
++ opt->backPrev = curBack + LZMA_NUM_REPS;
++ opt->prev1IsChar = False;
++ }
++
++ if (/*_maxMode && */lenTest == matchDistances[offs])
++ {
++ /* Try Match + Literal + Rep0 */
++ const Byte *data2 = data - (curBack + 1);
++ UInt32 lenTest2 = lenTest + 1;
++ UInt32 limit = lenTest2 + p->numFastBytes;
++ UInt32 nextRepMatchPrice;
++ if (limit > numAvailableBytesFull)
++ limit = numAvailableBytesFull;
++ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
++ lenTest2 -= lenTest + 1;
++ if (lenTest2 >= 2)
++ {
++ UInt32 state2 = kMatchNextStates[state];
++ UInt32 posStateNext = (position + lenTest) & p->pbMask;
++ UInt32 curAndLenCharPrice = curAndLenPrice +
++ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
++ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
++ data[lenTest], data2[lenTest], p->ProbPrices);
++ state2 = kLiteralNextStates[state2];
++ posStateNext = (posStateNext + 1) & p->pbMask;
++ nextRepMatchPrice = curAndLenCharPrice +
++ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
++ GET_PRICE_1(p->isRep[state2]);
++
++ /* for (; lenTest2 >= 2; lenTest2--) */
++ {
++ UInt32 offset = cur + lenTest + 1 + lenTest2;
++ UInt32 curAndLenPrice;
++ COptimal *opt;
++ while (lenEnd < offset)
++ p->opt[++lenEnd].price = kInfinityPrice;
++ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
++ opt = &p->opt[offset];
++ if (curAndLenPrice < opt->price)
++ {
++ opt->price = curAndLenPrice;
++ opt->posPrev = cur + lenTest + 1;
++ opt->backPrev = 0;
++ opt->prev1IsChar = True;
++ opt->prev2 = True;
++ opt->posPrev2 = cur;
++ opt->backPrev2 = curBack + LZMA_NUM_REPS;
++ }
++ }
++ }
++ offs += 2;
++ if (offs == numDistancePairs)
++ break;
++ curBack = matchDistances[offs + 1];
++ if (curBack >= kNumFullDistances)
++ GetPosSlot2(curBack, posSlot);
++ }
++ }
++ }
++ }
++}
++
++#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
++
++static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
++{
++ UInt32 numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
++ UInt32 lenMain, numDistancePairs;
++ const Byte *data;
++ UInt32 repLens[LZMA_NUM_REPS];
++ UInt32 repMaxIndex, i;
++ UInt32 *matchDistances;
++ UInt32 backMain;
++
++ if (!p->longestMatchWasFound)
++ {
++ lenMain = ReadMatchDistances(p, &numDistancePairs);
++ }
++ else
++ {
++ lenMain = p->longestMatchLength;
++ numDistancePairs = p->numDistancePairs;
++ p->longestMatchWasFound = False;
++ }
++
++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
++ if (numAvailableBytes > LZMA_MATCH_LEN_MAX)
++ numAvailableBytes = LZMA_MATCH_LEN_MAX;
++ if (numAvailableBytes < 2)
++ {
++ *backRes = (UInt32)(-1);
++ return 1;
++ }
++
++ repMaxIndex = 0;
++
++ for (i = 0; i < LZMA_NUM_REPS; i++)
++ {
++ const Byte *data2 = data - (p->reps[i] + 1);
++ UInt32 len;
++ if (data[0] != data2[0] || data[1] != data2[1])
++ {
++ repLens[i] = 0;
++ continue;
++ }
++ for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
++ if (len >= p->numFastBytes)
++ {
++ *backRes = i;
++ MovePos(p, len - 1);
++ return len;
++ }
++ repLens[i] = len;
++ if (len > repLens[repMaxIndex])
++ repMaxIndex = i;
++ }
++ matchDistances = p->matchDistances;
++ if (lenMain >= p->numFastBytes)
++ {
++ *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS;
++ MovePos(p, lenMain - 1);
++ return lenMain;
++ }
++
++ backMain = 0; /* for GCC */
++ if (lenMain >= 2)
++ {
++ backMain = matchDistances[numDistancePairs - 1];
++ while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
++ {
++ if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
++ break;
++ numDistancePairs -= 2;
++ lenMain = matchDistances[numDistancePairs - 2];
++ backMain = matchDistances[numDistancePairs - 1];
++ }
++ if (lenMain == 2 && backMain >= 0x80)
++ lenMain = 1;
++ }
++
++ if (repLens[repMaxIndex] >= 2)
++ {
++ if (repLens[repMaxIndex] + 1 >= lenMain ||
++ (repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9))) ||
++ (repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))))
++ {
++ UInt32 lenRes;
++ *backRes = repMaxIndex;
++ lenRes = repLens[repMaxIndex];
++ MovePos(p, lenRes - 1);
++ return lenRes;
++ }
++ }
++
++ if (lenMain >= 2 && numAvailableBytes > 2)
++ {
++ UInt32 i;
++ numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
++ p->longestMatchLength = ReadMatchDistances(p, &p->numDistancePairs);
++ if (p->longestMatchLength >= 2)
++ {
++ UInt32 newDistance = matchDistances[p->numDistancePairs - 1];
++ if ((p->longestMatchLength >= lenMain && newDistance < backMain) ||
++ (p->longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance)) ||
++ (p->longestMatchLength > lenMain + 1) ||
++ (p->longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)))
++ {
++ p->longestMatchWasFound = True;
++ *backRes = (UInt32)(-1);
++ return 1;
++ }
++ }
++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
++ for (i = 0; i < LZMA_NUM_REPS; i++)
++ {
++ UInt32 len;
++ const Byte *data2 = data - (p->reps[i] + 1);
++ if (data[1] != data2[1] || data[2] != data2[2])
++ {
++ repLens[i] = 0;
++ continue;
++ }
++ for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
++ if (len + 1 >= lenMain)
++ {
++ p->longestMatchWasFound = True;
++ *backRes = (UInt32)(-1);
++ return 1;
++ }
++ }
++ *backRes = backMain + LZMA_NUM_REPS;
++ MovePos(p, lenMain - 2);
++ return lenMain;
++ }
++ *backRes = (UInt32)(-1);
++ return 1;
++}
++
++static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
++{
++ UInt32 len;
++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
++ p->state = kMatchNextStates[p->state];
++ len = LZMA_MATCH_LEN_MIN;
++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
++ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
++}
++
++static SRes CheckErrors(CLzmaEnc *p)
++{
++ if (p->result != SZ_OK)
++ return p->result;
++ if (p->rc.res != SZ_OK)
++ p->result = SZ_ERROR_WRITE;
++ if (p->matchFinderBase.result != SZ_OK)
++ p->result = SZ_ERROR_READ;
++ if (p->result != SZ_OK)
++ p->finished = True;
++ return p->result;
++}
++
++static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
++{
++ /* ReleaseMFStream(); */
++ p->finished = True;
++ if (p->writeEndMark)
++ WriteEndMarker(p, nowPos & p->pbMask);
++ RangeEnc_FlushData(&p->rc);
++ RangeEnc_FlushStream(&p->rc);
++ return CheckErrors(p);
++}
++
++static void FillAlignPrices(CLzmaEnc *p)
++{
++ UInt32 i;
++ for (i = 0; i < kAlignTableSize; i++)
++ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
++ p->alignPriceCount = 0;
++}
++
++static void FillDistancesPrices(CLzmaEnc *p)
++{
++ UInt32 tempPrices[kNumFullDistances];
++ UInt32 i, lenToPosState;
++ for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
++ {
++ UInt32 posSlot = GetPosSlot1(i);
++ UInt32 footerBits = ((posSlot >> 1) - 1);
++ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
++ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
++ }
++
++ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
++ {
++ UInt32 posSlot;
++ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
++ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
++ for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
++ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
++ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
++ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
++
++ {
++ UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
++ UInt32 i;
++ for (i = 0; i < kStartPosModelIndex; i++)
++ distancesPrices[i] = posSlotPrices[i];
++ for (; i < kNumFullDistances; i++)
++ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
++ }
++ }
++ p->matchPriceCount = 0;
++}
++
++void LzmaEnc_Construct(CLzmaEnc *p)
++{
++ RangeEnc_Construct(&p->rc);
++ MatchFinder_Construct(&p->matchFinderBase);
++ #ifdef COMPRESS_MF_MT
++ MatchFinderMt_Construct(&p->matchFinderMt);
++ p->matchFinderMt.MatchFinder = &p->matchFinderBase;
++ #endif
++
++ {
++ CLzmaEncProps props;
++ LzmaEncProps_Init(&props);
++ LzmaEnc_SetProps(p, &props);
++ }
++
++ #ifndef LZMA_LOG_BSR
++ LzmaEnc_FastPosInit(p->g_FastPos);
++ #endif
++
++ LzmaEnc_InitPriceTables(p->ProbPrices);
++ p->litProbs = 0;
++ p->saveState.litProbs = 0;
++}
++
++CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
++{
++ void *p;
++ p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
++ if (p != 0)
++ LzmaEnc_Construct((CLzmaEnc *)p);
++ return p;
++}
++
++void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
++{
++ alloc->Free(alloc, p->litProbs);
++ alloc->Free(alloc, p->saveState.litProbs);
++ p->litProbs = 0;
++ p->saveState.litProbs = 0;
++}
++
++void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ #ifdef COMPRESS_MF_MT
++ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
++ #endif
++ MatchFinder_Free(&p->matchFinderBase, allocBig);
++ LzmaEnc_FreeLits(p, alloc);
++ RangeEnc_Free(&p->rc, alloc);
++}
++
++void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
++ alloc->Free(alloc, p);
++}
++
++static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
++{
++ UInt32 nowPos32, startPos32;
++ if (p->inStream != 0)
++ {
++ p->matchFinderBase.stream = p->inStream;
++ p->matchFinder.Init(p->matchFinderObj);
++ p->inStream = 0;
++ }
++
++ if (p->finished)
++ return p->result;
++ RINOK(CheckErrors(p));
++
++ nowPos32 = (UInt32)p->nowPos64;
++ startPos32 = nowPos32;
++
++ if (p->nowPos64 == 0)
++ {
++ UInt32 numDistancePairs;
++ Byte curByte;
++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
++ return Flush(p, nowPos32);
++ ReadMatchDistances(p, &numDistancePairs);
++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
++ p->state = kLiteralNextStates[p->state];
++ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
++ LitEnc_Encode(&p->rc, p->litProbs, curByte);
++ p->additionalOffset--;
++ nowPos32++;
++ }
++
++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
++ for (;;)
++ {
++ UInt32 pos, len, posState;
++
++ if (p->fastMode)
++ len = GetOptimumFast(p, &pos);
++ else
++ len = GetOptimum(p, nowPos32, &pos);
++
++ #ifdef SHOW_STAT2
++ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos);
++ #endif
++
++ posState = nowPos32 & p->pbMask;
++ if (len == 1 && pos == 0xFFFFFFFF)
++ {
++ Byte curByte;
++ CLzmaProb *probs;
++ const Byte *data;
++
++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
++ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
++ curByte = *data;
++ probs = LIT_PROBS(nowPos32, *(data - 1));
++ if (IsCharState(p->state))
++ LitEnc_Encode(&p->rc, probs, curByte);
++ else
++ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
++ p->state = kLiteralNextStates[p->state];
++ }
++ else
++ {
++ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
++ if (pos < LZMA_NUM_REPS)
++ {
++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
++ if (pos == 0)
++ {
++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
++ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
++ }
++ else
++ {
++ UInt32 distance = p->reps[pos];
++ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
++ if (pos == 1)
++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
++ else
++ {
++ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
++ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
++ if (pos == 3)
++ p->reps[3] = p->reps[2];
++ p->reps[2] = p->reps[1];
++ }
++ p->reps[1] = p->reps[0];
++ p->reps[0] = distance;
++ }
++ if (len == 1)
++ p->state = kShortRepNextStates[p->state];
++ else
++ {
++ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
++ p->state = kRepNextStates[p->state];
++ }
++ }
++ else
++ {
++ UInt32 posSlot;
++ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
++ p->state = kMatchNextStates[p->state];
++ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
++ pos -= LZMA_NUM_REPS;
++ GetPosSlot(pos, posSlot);
++ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
++
++ if (posSlot >= kStartPosModelIndex)
++ {
++ UInt32 footerBits = ((posSlot >> 1) - 1);
++ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
++ UInt32 posReduced = pos - base;
++
++ if (posSlot < kEndPosModelIndex)
++ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
++ else
++ {
++ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
++ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
++ p->alignPriceCount++;
++ }
++ }
++ p->reps[3] = p->reps[2];
++ p->reps[2] = p->reps[1];
++ p->reps[1] = p->reps[0];
++ p->reps[0] = pos;
++ p->matchPriceCount++;
++ }
++ }
++ p->additionalOffset -= len;
++ nowPos32 += len;
++ if (p->additionalOffset == 0)
++ {
++ UInt32 processed;
++ if (!p->fastMode)
++ {
++ if (p->matchPriceCount >= (1 << 7))
++ FillDistancesPrices(p);
++ if (p->alignPriceCount >= kAlignTableSize)
++ FillAlignPrices(p);
++ }
++ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
++ break;
++ processed = nowPos32 - startPos32;
++ if (useLimits)
++ {
++ if (processed + kNumOpts + 300 >= maxUnpackSize ||
++ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
++ break;
++ }
++ else if (processed >= (1 << 15))
++ {
++ p->nowPos64 += nowPos32 - startPos32;
++ return CheckErrors(p);
++ }
++ }
++ }
++ p->nowPos64 += nowPos32 - startPos32;
++ return Flush(p, nowPos32);
++}
++
++#define kBigHashDicLimit ((UInt32)1 << 24)
++
++static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ UInt32 beforeSize = kNumOpts;
++ Bool btMode;
++ if (!RangeEnc_Alloc(&p->rc, alloc))
++ return SZ_ERROR_MEM;
++ btMode = (p->matchFinderBase.btMode != 0);
++ #ifdef COMPRESS_MF_MT
++ p->mtMode = (p->multiThread && !p->fastMode && btMode);
++ #endif
++
++ {
++ unsigned lclp = p->lc + p->lp;
++ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
++ {
++ LzmaEnc_FreeLits(p, alloc);
++ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
++ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
++ if (p->litProbs == 0 || p->saveState.litProbs == 0)
++ {
++ LzmaEnc_FreeLits(p, alloc);
++ return SZ_ERROR_MEM;
++ }
++ p->lclp = lclp;
++ }
++ }
++
++ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
++
++ if (beforeSize + p->dictSize < keepWindowSize)
++ beforeSize = keepWindowSize - p->dictSize;
++
++ #ifdef COMPRESS_MF_MT
++ if (p->mtMode)
++ {
++ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
++ p->matchFinderObj = &p->matchFinderMt;
++ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
++ }
++ else
++ #endif
++ {
++ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
++ return SZ_ERROR_MEM;
++ p->matchFinderObj = &p->matchFinderBase;
++ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
++ }
++ return SZ_OK;
++}
++
++void LzmaEnc_Init(CLzmaEnc *p)
++{
++ UInt32 i;
++ p->state = 0;
++ for(i = 0 ; i < LZMA_NUM_REPS; i++)
++ p->reps[i] = 0;
++
++ RangeEnc_Init(&p->rc);
++
++
++ for (i = 0; i < kNumStates; i++)
++ {
++ UInt32 j;
++ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
++ {
++ p->isMatch[i][j] = kProbInitValue;
++ p->isRep0Long[i][j] = kProbInitValue;
++ }
++ p->isRep[i] = kProbInitValue;
++ p->isRepG0[i] = kProbInitValue;
++ p->isRepG1[i] = kProbInitValue;
++ p->isRepG2[i] = kProbInitValue;
++ }
++
++ {
++ UInt32 num = 0x300 << (p->lp + p->lc);
++ for (i = 0; i < num; i++)
++ p->litProbs[i] = kProbInitValue;
++ }
++
++ {
++ for (i = 0; i < kNumLenToPosStates; i++)
++ {
++ CLzmaProb *probs = p->posSlotEncoder[i];
++ UInt32 j;
++ for (j = 0; j < (1 << kNumPosSlotBits); j++)
++ probs[j] = kProbInitValue;
++ }
++ }
++ {
++ for(i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
++ p->posEncoders[i] = kProbInitValue;
++ }
++
++ LenEnc_Init(&p->lenEnc.p);
++ LenEnc_Init(&p->repLenEnc.p);
++
++ for (i = 0; i < (1 << kNumAlignBits); i++)
++ p->posAlignEncoder[i] = kProbInitValue;
++
++ p->longestMatchWasFound = False;
++ p->optimumEndIndex = 0;
++ p->optimumCurrentIndex = 0;
++ p->additionalOffset = 0;
++
++ p->pbMask = (1 << p->pb) - 1;
++ p->lpMask = (1 << p->lp) - 1;
++}
++
++void LzmaEnc_InitPrices(CLzmaEnc *p)
++{
++ if (!p->fastMode)
++ {
++ FillDistancesPrices(p);
++ FillAlignPrices(p);
++ }
++
++ p->lenEnc.tableSize =
++ p->repLenEnc.tableSize =
++ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
++ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
++ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
++}
++
++static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ UInt32 i;
++ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
++ if (p->dictSize <= ((UInt32)1 << i))
++ break;
++ p->distTableSize = i * 2;
++
++ p->finished = False;
++ p->result = SZ_OK;
++ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
++ LzmaEnc_Init(p);
++ LzmaEnc_InitPrices(p);
++ p->nowPos64 = 0;
++ return SZ_OK;
++}
++
++static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
++ ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ p->inStream = inStream;
++ p->rc.outStream = outStream;
++ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
++}
++
++SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
++ ISeqInStream *inStream, UInt32 keepWindowSize,
++ ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ p->inStream = inStream;
++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
++}
++
++static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
++{
++ p->seqBufInStream.funcTable.Read = MyRead;
++ p->seqBufInStream.data = src;
++ p->seqBufInStream.rem = srcLen;
++}
++
++SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
++ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ LzmaEnc_SetInputBuf(p, src, srcLen);
++ p->inStream = &p->seqBufInStream.funcTable;
++ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
++}
++
++void LzmaEnc_Finish(CLzmaEncHandle pp)
++{
++ #ifdef COMPRESS_MF_MT
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ if (p->mtMode)
++ MatchFinderMt_ReleaseStream(&p->matchFinderMt);
++ #endif
++}
++
++typedef struct _CSeqOutStreamBuf
++{
++ ISeqOutStream funcTable;
++ Byte *data;
++ SizeT rem;
++ Bool overflow;
++} CSeqOutStreamBuf;
++
++static size_t MyWrite(void *pp, const void *data, size_t size)
++{
++ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
++ if (p->rem < size)
++ {
++ size = p->rem;
++ p->overflow = True;
++ }
++ memcpy(p->data, data, size);
++ p->rem -= size;
++ p->data += size;
++ return size;
++}
++
++
++UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
++{
++ const CLzmaEnc *p = (CLzmaEnc *)pp;
++ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
++}
++
++const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
++{
++ const CLzmaEnc *p = (CLzmaEnc *)pp;
++ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
++}
++
++SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
++ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ UInt64 nowPos64;
++ SRes res;
++ CSeqOutStreamBuf outStream;
++
++ outStream.funcTable.Write = MyWrite;
++ outStream.data = dest;
++ outStream.rem = *destLen;
++ outStream.overflow = False;
++
++ p->writeEndMark = False;
++ p->finished = False;
++ p->result = SZ_OK;
++
++ if (reInit)
++ LzmaEnc_Init(p);
++ LzmaEnc_InitPrices(p);
++ nowPos64 = p->nowPos64;
++ RangeEnc_Init(&p->rc);
++ p->rc.outStream = &outStream.funcTable;
++
++ res = LzmaEnc_CodeOneBlock(pp, True, desiredPackSize, *unpackSize);
++
++ *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
++ *destLen -= outStream.rem;
++ if (outStream.overflow)
++ return SZ_ERROR_OUTPUT_EOF;
++
++ return res;
++}
++
++SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
++ ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ SRes res = SZ_OK;
++
++ #ifdef COMPRESS_MF_MT
++ Byte allocaDummy[0x300];
++ int i = 0;
++ for (i = 0; i < 16; i++)
++ allocaDummy[i] = (Byte)i;
++ #endif
++
++ RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
++
++ for (;;)
++ {
++ res = LzmaEnc_CodeOneBlock(pp, False, 0, 0);
++ if (res != SZ_OK || p->finished != 0)
++ break;
++ if (progress != 0)
++ {
++ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
++ if (res != SZ_OK)
++ {
++ res = SZ_ERROR_PROGRESS;
++ break;
++ }
++ }
++ }
++ LzmaEnc_Finish(pp);
++ return res;
++}
++
++SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
++{
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++ int i;
++ UInt32 dictSize = p->dictSize;
++ if (*size < LZMA_PROPS_SIZE)
++ return SZ_ERROR_PARAM;
++ *size = LZMA_PROPS_SIZE;
++ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
++
++ for (i = 11; i <= 30; i++)
++ {
++ if (dictSize <= ((UInt32)2 << i))
++ {
++ dictSize = (2 << i);
++ break;
++ }
++ if (dictSize <= ((UInt32)3 << i))
++ {
++ dictSize = (3 << i);
++ break;
++ }
++ }
++
++ for (i = 0; i < 4; i++)
++ props[1 + i] = (Byte)(dictSize >> (8 * i));
++ return SZ_OK;
++}
++
++SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
++ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ SRes res;
++ CLzmaEnc *p = (CLzmaEnc *)pp;
++
++ CSeqOutStreamBuf outStream;
++
++ LzmaEnc_SetInputBuf(p, src, srcLen);
++
++ outStream.funcTable.Write = MyWrite;
++ outStream.data = dest;
++ outStream.rem = *destLen;
++ outStream.overflow = False;
++
++ p->writeEndMark = writeEndMark;
++ res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
++ progress, alloc, allocBig);
++
++ *destLen -= outStream.rem;
++ if (outStream.overflow)
++ return SZ_ERROR_OUTPUT_EOF;
++ return res;
++}
++
++SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
++ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
++ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
++{
++ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
++ SRes res;
++ if (p == 0)
++ return SZ_ERROR_MEM;
++
++ res = LzmaEnc_SetProps(p, props);
++ if (res == SZ_OK)
++ {
++ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
++ if (res == SZ_OK)
++ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
++ writeEndMark, progress, alloc, allocBig);
++ }
++
++ LzmaEnc_Destroy(p, alloc, allocBig);
++ return res;
++}
+--- a/mkfs.jffs2.c
++++ b/mkfs.jffs2.c
+@@ -1659,11 +1659,11 @@ int main(int argc, char **argv)
+ }
+ erase_block_size *= units;
+
+- /* If it's less than 8KiB, they're not allowed */
+- if (erase_block_size < 0x2000) {
+- fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
++ /* If it's less than 4KiB, they're not allowed */
++ if (erase_block_size < 0x1000) {
++ fprintf(stderr, "Erase size 0x%x too small. Increasing to 4KiB minimum\n",
+ erase_block_size);
+- erase_block_size = 0x2000;
++ erase_block_size = 0x1000;
+ }
+ break;
+ }
diff --git a/tools/mtd-utils/patches/134-freebsd_loff_t.patch b/tools/mtd-utils/patches/134-freebsd_loff_t.patch
new file mode 100644
index 0000000..2d141bd
--- /dev/null
+++ b/tools/mtd-utils/patches/134-freebsd_loff_t.patch
@@ -0,0 +1,14 @@
+--- a/include/mtd/mtd-abi.h
++++ b/include/mtd/mtd-abi.h
+@@ -171,9 +171,9 @@ struct otp_info {
+ /* Get info about OOB modes (e.g., RAW, PLACE, AUTO) - legacy interface */
+ #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)
+ /* Check if an eraseblock is bad */
+-#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t)
++#define MEMGETBADBLOCK _IOW('M', 11, loff_t)
+ /* Mark an eraseblock as bad */
+-#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t)
++#define MEMSETBADBLOCK _IOW('M', 12, loff_t)
+ /* Set OTP (One-Time Programmable) mode (factory vs. user) */
+ #define OTPSELECT _IOR('M', 13, int)
+ /* Get number of OTP (One-Time Programmable) regions */
diff --git a/tools/mtd-utils/patches/135-mkubifs_optional_lzo.patch b/tools/mtd-utils/patches/135-mkubifs_optional_lzo.patch
new file mode 100644
index 0000000..90d4ef4
--- /dev/null
+++ b/tools/mtd-utils/patches/135-mkubifs_optional_lzo.patch
@@ -0,0 +1,119 @@
+--- a/mkfs.ubifs/compr.c
++++ b/mkfs.ubifs/compr.c
+@@ -24,7 +24,6 @@
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <string.h>
+-#include <lzo/lzo1x.h>
+ #include <linux/types.h>
+
+ #define crc32 __zlib_crc32
+@@ -34,7 +33,6 @@
+ #include "compr.h"
+ #include "mkfs.ubifs.h"
+
+-static void *lzo_mem;
+ static unsigned long long errcnt = 0;
+ static struct ubifs_info *c = &info_;
+
+@@ -85,6 +83,25 @@ static int zlib_deflate(void *in_buf, si
+ return 0;
+ }
+
++#ifndef WITHOUT_LZO
++#include <lzo/lzo1x.h>
++
++static void *lzo_mem;
++
++static int lzo_init(void)
++{
++ lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
++ if (!lzo_mem)
++ return -1;
++
++ return 0;
++}
++
++static void lzo_fini(void)
++{
++ free(lzo_mem);
++}
++
+ static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
+ size_t *out_len)
+ {
+@@ -102,6 +119,12 @@ static int lzo_compress(void *in_buf, si
+
+ return 0;
+ }
++#else
++static inline int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
++ size_t *out_len) { return -1; }
++static inline int lzo_init(void) { return 0; }
++static inline void lzo_fini(void) { }
++#endif
+
+ static int no_compress(void *in_buf, size_t in_len, void *out_buf,
+ size_t *out_len)
+@@ -122,7 +145,6 @@ static int favor_lzo_compress(void *in_b
+ lzo_len = zlib_len = *out_len;
+ lzo_ret = lzo_compress(in_buf, in_len, out_buf, &lzo_len);
+ zlib_ret = zlib_deflate(in_buf, in_len, zlib_buf, &zlib_len);
+-
+ if (lzo_ret && zlib_ret)
+ /* Both compressors failed */
+ return -1;
+@@ -197,23 +219,28 @@ int compress_data(void *in_buf, size_t i
+
+ int init_compression(void)
+ {
+- lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
+- if (!lzo_mem)
+- return -1;
++ int ret;
++
++ ret = lzo_init();
++ if (ret)
++ goto err;
+
+ zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
+- if (!zlib_buf) {
+- free(lzo_mem);
+- return -1;
+- }
++ if (!zlib_buf)
++ goto err_lzo;
+
+ return 0;
++
++err_lzo:
++ lzo_fini();
++err:
++ return ret;
+ }
+
+ void destroy_compression(void)
+ {
+ free(zlib_buf);
+- free(lzo_mem);
++ lzo_fini();
+ if (errcnt)
+ fprintf(stderr, "%llu compression errors occurred\n", errcnt);
+ }
+--- a/Makefile
++++ b/Makefile
+@@ -108,7 +108,13 @@ $(call _mkdep,lib/,libmtd.a)
+ obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o \
+ hashtable/hashtable.o hashtable/hashtable_itr.o
+ LDFLAGS_mkfs.ubifs = $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
+-LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid
++ifeq ($(WITHOUT_LZO), 1)
++ CPPFLAGS += -DWITHOUT_LZO
++else
++ LZOLDLIBS = -llzo2
++endif
++
++LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
+ $(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
+
+ #
diff --git a/tools/mtd-utils/patches/136-mkfs.ubifs-xz-support.patch b/tools/mtd-utils/patches/136-mkfs.ubifs-xz-support.patch
new file mode 100644
index 0000000..d97c244
--- /dev/null
+++ b/tools/mtd-utils/patches/136-mkfs.ubifs-xz-support.patch
@@ -0,0 +1,378 @@
+--- a/Makefile
++++ b/Makefile
+@@ -4,7 +4,7 @@
+ VERSION = 1.5.1
+
+ CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS)
+-CPPFLAGS += -I./include/linux/lzma
++CPPFLAGS += $(XZCPPFLAGS) -I./include/linux/lzma
+
+ ifeq ($(WITHOUT_XATTR), 1)
+ CPPFLAGS += -DWITHOUT_XATTR
+@@ -113,8 +113,13 @@ ifeq ($(WITHOUT_LZO), 1)
+ else
+ LZOLDLIBS = -llzo2
+ endif
++ifeq ($(WITHOUT_XZ), 1)
++ CPPFLAGS += -DWITHOUT_XZ
++else
++ XZLDLIBS = -llzma
++endif
+
+-LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
++LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) $(XZLDLIBS) -lm -luuid
+ $(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
+
+ #
+--- a/mkfs.ubifs/compr.c
++++ b/mkfs.ubifs/compr.c
+@@ -126,6 +126,114 @@ static inline int lzo_init(void) { retur
+ static inline void lzo_fini(void) { }
+ #endif
+
++#ifndef WITHOUT_XZ
++
++#include <lzma.h>
++
++struct xz_ctx {
++ lzma_filter filters[3];
++ lzma_options_lzma opts;
++};
++
++static struct xz_ctx *xz_ctx;
++
++#define LZMA_COMPRESSION_LEVEL 9
++
++static struct xz_ctx *xz_ctx_init(void)
++{
++ struct xz_ctx *ctx;
++ lzma_options_lzma *opts_lzma;
++ uint32_t preset;
++ int ret;
++
++ ctx = malloc(sizeof(struct xz_ctx));
++ if (ctx == NULL)
++ goto err;
++
++ memset(ctx, 0, sizeof(struct xz_ctx));
++
++ opts_lzma = &ctx->opts;
++
++ preset = LZMA_COMPRESSION_LEVEL | LZMA_PRESET_EXTREME;
++ ret = lzma_lzma_preset(opts_lzma, preset);
++ if (ret)
++ goto err_free_ctx;
++
++ /* TODO: allow to specify LZMA options via command line */
++#if 0
++ opts_lzma->lc = 3;
++ opts_lzma->lp = 0;
++ opts_lzma->pb = 2;
++ opts_lzma->nice_len = 64;
++#else
++ opts_lzma->lc = 0;
++ opts_lzma->lp = 2;
++ opts_lzma->pb = 2;
++ opts_lzma->nice_len = 64;
++#endif
++
++ ctx->filters[0].id = LZMA_FILTER_LZMA2;
++ ctx->filters[0].options = opts_lzma;
++ ctx->filters[1].id = LZMA_VLI_UNKNOWN;
++
++ return ctx;
++
++err_free_ctx:
++ free(ctx);
++err:
++ return NULL;
++}
++
++static void xz_ctx_free(struct xz_ctx *ctx)
++{
++ free(ctx);
++}
++
++static int xz_init(void)
++{
++ xz_ctx = xz_ctx_init();
++ if (xz_ctx == NULL)
++ return -1;
++
++ return 0;
++}
++
++static void xz_fini(void)
++{
++ xz_ctx_free(xz_ctx);
++}
++
++static int xz_compress(void *in_buf, size_t in_len, void *out_buf,
++ size_t *out_len)
++{
++ size_t ret_len;
++ lzma_ret ret_xz;
++ int ret;
++
++ ret = -1;
++
++ ret_len = 0;
++ ret_xz = lzma_stream_buffer_encode(xz_ctx->filters, LZMA_CHECK_CRC32,
++ NULL, in_buf, in_len, out_buf,
++ &ret_len, *out_len);
++ if (ret_xz != LZMA_OK) {
++ fprintf(stderr, "XZ error: %d\n", (int) ret_xz);
++ goto out;
++ }
++
++ *out_len = ret_len;
++
++ ret = 0;
++out:
++ return ret;
++}
++#else
++static inline int xz_init(void) { return 0; }
++static inline void xz_fini(void) { }
++static inline int xz_compress(void *in_buf, size_t in_len, void *out_buf,
++ size_t *out_len) { return -1; }
++#endif
++
+ static int no_compress(void *in_buf, size_t in_len, void *out_buf,
+ size_t *out_len)
+ {
+@@ -198,6 +306,9 @@ int compress_data(void *in_buf, size_t i
+ case MKFS_UBIFS_COMPR_LZO:
+ ret = lzo_compress(in_buf, in_len, out_buf, out_len);
+ break;
++ case MKFS_UBIFS_COMPR_XZ:
++ ret = xz_compress(in_buf, in_len, out_buf, out_len);
++ break;
+ case MKFS_UBIFS_COMPR_ZLIB:
+ ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
+ break;
+@@ -225,12 +336,18 @@ int init_compression(void)
+ if (ret)
+ goto err;
+
++ ret = xz_init();
++ if (ret)
++ goto err_lzo;
++
+ zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
+ if (!zlib_buf)
+- goto err_lzo;
++ goto err_xz;
+
+ return 0;
+
++err_xz:
++ xz_fini();
+ err_lzo:
+ lzo_fini();
+ err:
+@@ -240,6 +357,7 @@ err:
+ void destroy_compression(void)
+ {
+ free(zlib_buf);
++ xz_fini();
+ lzo_fini();
+ if (errcnt)
+ fprintf(stderr, "%llu compression errors occurred\n", errcnt);
+--- a/mkfs.ubifs/compr.h
++++ b/mkfs.ubifs/compr.h
+@@ -36,6 +36,7 @@ enum compression_type
+ MKFS_UBIFS_COMPR_NONE,
+ MKFS_UBIFS_COMPR_LZO,
+ MKFS_UBIFS_COMPR_ZLIB,
++ MKFS_UBIFS_COMPR_XZ,
+ };
+
+ int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
+--- a/mkfs.ubifs/mkfs.ubifs.c
++++ b/mkfs.ubifs/mkfs.ubifs.c
+@@ -99,6 +99,9 @@ struct ubifs_info info_;
+ static struct ubifs_info *c = &info_;
+ static libubi_t ubi;
+
++static int force_compr_set;
++static int force_compr;
++
+ /* Debug levels are: 0 (none), 1 (statistics), 2 (files) ,3 (more details) */
+ int debug_level;
+ int verbose;
+@@ -133,7 +136,7 @@ static struct inum_mapping **hash_table;
+ /* Inode creation sequence number */
+ static unsigned long long creat_sqnum;
+
+-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQq";
++static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:z:j:R:l:j:UQq";
+
+ static const struct option longopts[] = {
+ {"root", 1, NULL, 'r'},
+@@ -151,6 +154,7 @@ static const struct option longopts[] =
+ {"reserved", 1, NULL, 'R'},
+ {"compr", 1, NULL, 'x'},
+ {"favor-percent", 1, NULL, 'X'},
++ {"force-compr", 1, NULL, 'z'},
+ {"fanout", 1, NULL, 'f'},
+ {"space-fixup", 0, NULL, 'F'},
+ {"keyhash", 1, NULL, 'k'},
+@@ -178,11 +182,13 @@ static const char *helptext =
+ "-o, --output=FILE output to FILE\n"
+ "-j, --jrn-size=SIZE journal size\n"
+ "-R, --reserved=SIZE how much space should be reserved for the super-user\n"
+-"-x, --compr=TYPE compression type - \"lzo\", \"favor_lzo\", \"zlib\" or\n"
+-" \"none\" (default: \"lzo\")\n"
++"-x, --compr=TYPE default compression type - \"lzo\", \"favor_lzo\",\n"
++" \"zlib\" or \"none\" (default: \"lzo\")\n"
+ "-X, --favor-percent may only be used with favor LZO compression and defines\n"
+ " how many percent better zlib should compress to make\n"
+ " mkfs.ubifs use zlib instead of LZO (default 20%)\n"
++"-z, --force-compr=TYPE force to build the fs with different compression -\n"
++" \"lzo\", \"zlib\" or \"none\"\n"
+ "-f, --fanout=NUM fanout NUM (default: 8)\n"
+ "-F, --space-fixup file-system free space has to be fixed up on first mount\n"
+ " (requires kernel version 3.0 or greater)\n"
+@@ -472,6 +478,43 @@ static int open_ubi(const char *node)
+ return 0;
+ }
+
++static const char *get_compr_str(int compr)
++{
++ switch (compr) {
++ case UBIFS_COMPR_LZO:
++ return "lzo";
++ case UBIFS_COMPR_ZLIB:
++ return "zlib";
++ case UBIFS_COMPR_XZ:
++ return "xz";
++ case UBIFS_COMPR_NONE:
++ return "none";
++ }
++
++ return "unknown";
++}
++
++static int get_compr_option(char *opt, int *compr_type, int *favor_lzo)
++{
++ *compr_type = UBIFS_COMPR_LZO;
++
++ if (favor_lzo)
++ *favor_lzo = 0;
++
++ if (favor_lzo && strcmp(optarg, "favor_lzo") == 0)
++ *favor_lzo = 1;
++ else if (strcmp(optarg, "zlib") == 0)
++ *compr_type = UBIFS_COMPR_ZLIB;
++ else if (strcmp(optarg, "xz") == 0)
++ *compr_type = UBIFS_COMPR_XZ;
++ else if (strcmp(optarg, "none") == 0)
++ *compr_type = UBIFS_COMPR_NONE;
++ else if (strcmp(optarg, "lzo") != 0)
++ return -1;
++
++ return 0;
++}
++
+ static int get_options(int argc, char**argv)
+ {
+ int opt, i;
+@@ -594,14 +637,13 @@ static int get_options(int argc, char**a
+ return err_msg("bad key hash");
+ break;
+ case 'x':
+- if (strcmp(optarg, "favor_lzo") == 0)
+- c->favor_lzo = 1;
+- else if (strcmp(optarg, "zlib") == 0)
+- c->default_compr = UBIFS_COMPR_ZLIB;
+- else if (strcmp(optarg, "none") == 0)
+- c->default_compr = UBIFS_COMPR_NONE;
+- else if (strcmp(optarg, "lzo") != 0)
+- return err_msg("bad compressor name");
++ if (get_compr_option(optarg, &c->default_compr,
++ &c->favor_lzo))
++ return err_msg("bad compressor name '%s'",
++ optarg);
++ if (c->default_compr == UBIFS_COMPR_XZ)
++ return err_msg("'%s' can't be used as default compressor",
++ optarg);
+ break;
+ case 'X':
+ c->favor_percent = strtol(optarg, &endp, 0);
+@@ -610,6 +652,12 @@ static int get_options(int argc, char**a
+ return err_msg("bad favor LZO percent '%s'",
+ optarg);
+ break;
++ case 'z':
++ if (get_compr_option(optarg, &force_compr, NULL))
++ return err_msg("bad forced compressor name '%s'",
++ optarg);
++ force_compr_set = 1;
++ break;
+ case 'j':
+ c->max_bud_bytes = get_bytes(optarg);
+ if (c->max_bud_bytes <= 0)
+@@ -684,6 +732,9 @@ static int get_options(int argc, char**a
+ c->min_io_size = 8;
+ c->rp_size = add_space_overhead(c->rp_size);
+
++ if (force_compr_set == 0)
++ force_compr = c->default_compr;
++
+ if (verbose) {
+ printf("mkfs.ubifs\n");
+ printf("\troot: %s\n", root);
+@@ -693,17 +744,10 @@ static int get_options(int argc, char**a
+ printf("\toutput: %s\n", output);
+ printf("\tjrn_size: %llu\n", c->max_bud_bytes);
+ printf("\treserved: %llu\n", c->rp_size);
+- switch (c->default_compr) {
+- case UBIFS_COMPR_LZO:
+- printf("\tcompr: lzo\n");
+- break;
+- case UBIFS_COMPR_ZLIB:
+- printf("\tcompr: zlib\n");
+- break;
+- case UBIFS_COMPR_NONE:
+- printf("\tcompr: none\n");
+- break;
+- }
++ printf("\tcompr: %s\n", get_compr_str(c->default_compr));
++ if (force_compr_set)
++ printf("\tforced compr: %s\n",
++ get_compr_str(force_compr));
+ printf("\tkeyhash: %s\n", (c->key_hash == key_r5_hash) ?
+ "r5" : "test");
+ printf("\tfanout: %d\n", c->fanout);
+@@ -1284,7 +1328,7 @@ static int add_file(const char *path_nam
+ use_compr = UBIFS_COMPR_LZO;
+ else
+ #endif
+- use_compr = c->default_compr;
++ use_compr = force_compr;
+ compr_type = compress_data(buf, bytes_read, &dn->data,
+ &out_len, use_compr);
+ dn->compr_type = cpu_to_le16(compr_type);
+--- a/mkfs.ubifs/mkfs.ubifs.h
++++ b/mkfs.ubifs/mkfs.ubifs.h
+@@ -83,6 +83,9 @@
+ #if MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
+ #error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
+ #endif
++#if MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
++#error MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
++#endif
+
+ extern int verbose;
+ extern int debug_level;
+--- a/include/mtd/ubifs-media.h
++++ b/include/mtd/ubifs-media.h
+@@ -313,6 +313,7 @@ enum {
+ UBIFS_COMPR_NONE,
+ UBIFS_COMPR_LZO,
+ UBIFS_COMPR_ZLIB,
++ UBIFS_COMPR_XZ,
+ UBIFS_COMPR_TYPES_CNT,
+ };
+
diff --git a/tools/mtd-utils/patches/137-no_extern_inline.patch b/tools/mtd-utils/patches/137-no_extern_inline.patch
new file mode 100644
index 0000000..d871d67
--- /dev/null
+++ b/tools/mtd-utils/patches/137-no_extern_inline.patch
@@ -0,0 +1,41 @@
+--- a/mkfs.ubifs/hashtable/hashtable_itr.c
++++ b/mkfs.ubifs/hashtable/hashtable_itr.c
+@@ -35,18 +35,6 @@ hashtable_iterator(struct hashtable *h)
+ }
+
+ /*****************************************************************************/
+-/* key - return the key of the (key,value) pair at the current position */
+-/* value - return the value of the (key,value) pair at the current position */
+-
+-void *
+-hashtable_iterator_key(struct hashtable_itr *i)
+-{ return i->e->k; }
+-
+-void *
+-hashtable_iterator_value(struct hashtable_itr *i)
+-{ return i->e->v; }
+-
+-/*****************************************************************************/
+ /* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+--- a/mkfs.ubifs/hashtable/hashtable_itr.h
++++ b/mkfs.ubifs/hashtable/hashtable_itr.h
+@@ -28,7 +28,7 @@ hashtable_iterator(struct hashtable *h);
+ /* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+-extern inline void *
++static inline void *
+ hashtable_iterator_key(struct hashtable_itr *i)
+ {
+ return i->e->k;
+@@ -37,7 +37,7 @@ hashtable_iterator_key(struct hashtable_
+ /*****************************************************************************/
+ /* value - return the value of the (key,value) pair at the current position */
+
+-extern inline void *
++static inline void *
+ hashtable_iterator_value(struct hashtable_itr *i)
+ {
+ return i->e->v;
diff --git a/tools/mtd-utils/patches/200-libubigen-add-ubigen_write_terminator-function.patch b/tools/mtd-utils/patches/200-libubigen-add-ubigen_write_terminator-function.patch
new file mode 100644
index 0000000..95ce1e9
--- /dev/null
+++ b/tools/mtd-utils/patches/200-libubigen-add-ubigen_write_terminator-function.patch
@@ -0,0 +1,89 @@
+--- a/ubi-utils/libubigen.c
++++ b/ubi-utils/libubigen.c
+@@ -122,8 +122,9 @@ int ubigen_add_volume(const struct ubige
+ return 0;
+ }
+
+-void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+- struct ubi_ec_hdr *hdr, long long ec)
++static void __ubigen_init_ec_hdr(const struct ubigen_info *ui,
++ struct ubi_ec_hdr *hdr, long long ec,
++ int eof)
+ {
+ uint32_t crc;
+
+@@ -136,10 +137,22 @@ void ubigen_init_ec_hdr(const struct ubi
+ hdr->data_offset = cpu_to_be32(ui->data_offs);
+ hdr->image_seq = cpu_to_be32(ui->image_seq);
+
++ if (eof) {
++ hdr->padding1[0] = 'E';
++ hdr->padding1[1] = 'O';
++ hdr->padding1[2] = 'F';
++ }
++
+ crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+ hdr->hdr_crc = cpu_to_be32(crc);
+ }
+
++void ubigen_init_ec_hdr(const struct ubigen_info *ui,
++ struct ubi_ec_hdr *hdr, long long ec)
++{
++ __ubigen_init_ec_hdr(ui, hdr, ec, 0);
++}
++
+ void ubigen_init_vid_hdr(const struct ubigen_info *ui,
+ const struct ubigen_vol_info *vi,
+ struct ubi_vid_hdr *hdr, int lnum,
+@@ -307,6 +320,39 @@ int ubigen_write_layout_vol(const struct
+ }
+
+ free(outbuf);
++ return 0;
++
++out_free:
++ free(outbuf);
++ return -1;
++}
++
++int ubigen_write_eof_markers(const struct ubigen_info *ui, long long ec,
++ int count, int out_fd)
++{
++ char *outbuf;
++ int peb_size = ui->peb_size;
++
++ outbuf = malloc(peb_size);
++ if (!outbuf) {
++ sys_errmsg("cannot allocate %d bytes of memory", peb_size);
++ return -1;
++ }
++
++ memset(outbuf, 0xFF, peb_size);
++ __ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec, 1);
++
++ while (count) {
++ if (write(out_fd, outbuf, peb_size) != peb_size) {
++ sys_errmsg("cannot write %d bytes to the output file",
++ peb_size);
++ goto out_free;
++ }
++
++ count--;
++ }
++
++ free(outbuf);
+ return 0;
+
+ out_free:
+--- a/ubi-utils/include/libubigen.h
++++ b/ubi-utils/include/libubigen.h
+@@ -188,6 +188,9 @@ int ubigen_write_layout_vol(const struct
+ long long ec1, long long ec2,
+ struct ubi_vtbl_record *vtbl, int fd);
+
++int ubigen_write_eof_markers(const struct ubigen_info *ui, long long ec,
++ int count, int out_fd);
++
+ #ifdef __cplusplus
+ }
+ #endif
diff --git a/tools/mtd-utils/patches/201-ubinize-add-terminator-support.patch b/tools/mtd-utils/patches/201-ubinize-add-terminator-support.patch
new file mode 100644
index 0000000..cbb2802
--- /dev/null
+++ b/tools/mtd-utils/patches/201-ubinize-add-terminator-support.patch
@@ -0,0 +1,77 @@
+--- a/ubi-utils/ubinize.c
++++ b/ubi-utils/ubinize.c
+@@ -70,6 +70,8 @@ static const char optionsstr[] =
+ " (default is 1)\n"
+ "-Q, --image-seq=<num> 32-bit UBI image sequence number to use\n"
+ " (by default a random number is picked)\n"
++"-E, --eof-markers=<num> number of eof-markers to put at the end of the\n"
++" output image\n"
+ "-v, --verbose be verbose\n"
+ "-h, --help print help message\n"
+ "-V, --version print program version";
+@@ -79,7 +81,7 @@ static const char usage[] =
+ "\t\t[-x <num>] [-Q <num>] [-v] [-h] [-V] [--output=<filename>] [--peb-size=<bytes>]\n"
+ "\t\t[--min-io-size=<bytes>] [--sub-page-size=<bytes>] [--vid-hdr-offset=<num>]\n"
+ "\t\t[--erase-counter=<num>] [--ubi-ver=<num>] [--image-seq=<num>] [--verbose] [--help]\n"
+-"\t\t[--version] ini-file\n"
++"\t\t[--eof-markers=<num>] [--version] ini-file\n"
+ "Example: " PROGRAM_NAME " -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image\n"
+ " 'ubi.img' as described by configuration file 'cfg.ini'";
+
+@@ -125,6 +127,7 @@ static const struct option long_options[
+ { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' },
+ { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' },
+ { .name = "image-seq", .has_arg = 1, .flag = NULL, .val = 'Q' },
++ { .name = "eof-markers", .has_arg = 1, .flag = NULL, .val = 'E' },
+ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+@@ -144,6 +147,7 @@ struct args {
+ uint32_t image_seq;
+ int verbose;
+ dictionary *dict;
++ int eof_markers;
+ };
+
+ static struct args args = {
+@@ -162,7 +166,7 @@ static int parse_opt(int argc, char * co
+ int key, error = 0;
+ unsigned long int image_seq;
+
+- key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhV", long_options, NULL);
++ key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:E:vhV", long_options, NULL);
+ if (key == -1)
+ break;
+
+@@ -222,6 +226,12 @@ static int parse_opt(int argc, char * co
+ args.image_seq = image_seq;
+ break;
+
++ case 'E':
++ args.eof_markers = simple_strtoul(optarg, &error);
++ if (error)
++ return errmsg("bad number of eof-markers: \"%s\"", optarg);
++ break;
++
+ case 'v':
+ args.verbose = 1;
+ break;
+@@ -599,6 +609,18 @@ int main(int argc, char * const argv[])
+ printf("\n");
+ }
+
++ if (args.eof_markers) {
++ verbose(args.verbose, "writing %d eof-marker blocks",
++ args.eof_markers);
++
++ err = ubigen_write_eof_markers(&ui, args.ec, args.eof_markers,
++ args.out_fd);
++ if (err) {
++ errmsg("cannot write eof-marker blocks");
++ goto out_free;
++ }
++ }
++
+ verbose(args.verbose, "writing layout volume");
+
+ err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
diff --git a/tools/mtd-utils/patches/300-libfec_use_standard_unsigned_long.patch b/tools/mtd-utils/patches/300-libfec_use_standard_unsigned_long.patch
new file mode 100644
index 0000000..73a68b5
--- /dev/null
+++ b/tools/mtd-utils/patches/300-libfec_use_standard_unsigned_long.patch
@@ -0,0 +1,35 @@
+--- a/lib/libfec.c
++++ b/lib/libfec.c
+@@ -61,8 +61,6 @@ struct timeval {
+ };
+ #define gettimeofday(x, dummy) { (x)->ticks = clock() ; }
+ #define DIFF_T(a,b) (1+ 1000000*(a.ticks - b.ticks) / CLOCKS_PER_SEC )
+-typedef unsigned long u_long ;
+-typedef unsigned short u_short ;
+ #else /* typically, unix systems */
+ #include <sys/time.h>
+ #define DIFF_T(a,b) \
+@@ -75,12 +73,12 @@ typedef unsigned short u_short ;
+ t = x.tv_usec + 1000000* (x.tv_sec & 0xff ) ; \
+ }
+ #define TOCK(t) \
+- { u_long t1 ; TICK(t1) ; \
++ { unsigned long t1 ; TICK(t1) ; \
+ if (t1 < t) t = 256000000 + t1 - t ; \
+ else t = t1 - t ; \
+ if (t == 0) t = 1 ;}
+
+-u_long ticks[10]; /* vars for timekeeping */
++unsigned long ticks[10]; /* vars for timekeeping */
+ #else
+ #define DEB(x)
+ #define DDB(x)
+@@ -625,7 +623,7 @@ init_fec(void)
+ #define FEC_MAGIC 0xFECC0DEC
+
+ struct fec_parms {
+- u_long magic ;
++ unsigned long magic ;
+ int k, n ; /* parameters of the code */
+ gf *enc_matrix ;
+ } ;
diff --git a/tools/mtd-utils/patches/310-add-static-linking-option.patch b/tools/mtd-utils/patches/310-add-static-linking-option.patch
new file mode 100644
index 0000000..810aea9
--- /dev/null
+++ b/tools/mtd-utils/patches/310-add-static-linking-option.patch
@@ -0,0 +1,43 @@
+--- a/common.mk
++++ b/common.mk
+@@ -2,6 +2,16 @@ CC := $(CROSS)gcc
+ AR := $(CROSS)ar
+ RANLIB := $(CROSS)ranlib
+
++ifeq ($(STATIC),1)
++ define static_link
++ -Wl,-Bstatic $(1) -Wl,-Bdynamic
++ endef
++else
++ define static_link
++ $(1)
++ endef
++endif
++
+ # Stolen from Linux build system
+ comma = ,
+ try-run = $(shell set -e; ($(1)) >/dev/null 2>&1 && echo "$(2)" || echo "$(3)")
+--- a/Makefile
++++ b/Makefile
+@@ -89,10 +89,10 @@ obj-mkfs.jffs2 = compr_rtime.o compr_zli
+ compr_lzma.o lzma/LzFind.o lzma/LzmaEnc.o lzma/LzmaDec.o \
+ compr.o rbtree.o
+ LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+-LDLIBS_mkfs.jffs2 = -lz $(LZOLDLIBS)
++LDLIBS_mkfs.jffs2 = $(call static_link,-lz $(LZOLDLIBS))
+
+ LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+-LDLIBS_jffs2reader = -lz $(LZOLDLIBS)
++LDLIBS_jffs2reader = $(call static_link,-lz $(LZOLDLIBS))
+
+ $(foreach v,$(MTD_BINS),$(eval $(call mkdep,,$(v))))
+
+@@ -119,7 +119,7 @@ else
+ XZLDLIBS = -llzma
+ endif
+
+-LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) $(XZLDLIBS) -lm -luuid
++LDLIBS_mkfs.ubifs = $(call static_link,-lz $(LZOLDLIBS) $(XZLDLIBS)) -lm $(call static_link,-luuid)
+ $(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
+
+ #
diff --git a/tools/mtools/Makefile b/tools/mtools/Makefile
new file mode 100644
index 0000000..13de447
--- /dev/null
+++ b/tools/mtools/Makefile
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2012-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtools
+PKG_VERSION:=4.0.18
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=17b9f525c1ae3583a478338deb7fbc19
+PKG_CAT:=zcat
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_VARS += \
+ ac_cv_header_iconv_h=no
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) mcopy mmd
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/mcopy $(STAGING_DIR_HOST)/bin/
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/mmd $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mcopy
+ rm -f $(STAGING_DIR_HOST)/bin/mmd
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/mtools/patches/100-compile_fix.patch b/tools/mtools/patches/100-compile_fix.patch
new file mode 100644
index 0000000..698e156
--- /dev/null
+++ b/tools/mtools/patches/100-compile_fix.patch
@@ -0,0 +1,19 @@
+--- a/sysincludes.h
++++ b/sysincludes.h
+@@ -101,14 +101,8 @@ typedef void *caddr_t;
+ #if defined __GNUC__ && defined __STDC__
+ /* gcc -traditional doesn't have PACKED, UNUSED and NORETURN */
+ # define PACKED __attribute__ ((packed))
+-# if __GNUC__ == 2 && __GNUC_MINOR__ > 6 || __GNUC__ >= 3
+-/* gcc 2.6.3 doesn't have "unused" */ /* mool */
+-# define UNUSED(x) x __attribute__ ((unused));x
+-# define UNUSEDP __attribute__ ((unused))
+-# else
+-# define UNUSED(x) x
+-# define UNUSEDP /* */
+-# endif
++# define UNUSED(x) x
++# define UNUSEDP /* */
+ # define NORETURN __attribute__ ((noreturn))
+ #else
+ # define UNUSED(x) x
diff --git a/tools/padjffs2/Makefile b/tools/padjffs2/Makefile
new file mode 100644
index 0000000..0a583b8
--- /dev/null
+++ b/tools/padjffs2/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2011-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=padjffs2
+PKG_VERSION:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Prepare
+ mkdir -p $(HOST_BUILD_DIR)
+ $(CP) ./src/* $(HOST_BUILD_DIR)/
+ find $(HOST_BUILD_DIR) -name .svn | $(XARGS) rm -rf
+endef
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR)
+endef
+
+define Host/Configure
+endef
+
+define Host/Install
+ $(CP) $(HOST_BUILD_DIR)/padjffs2 $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/padjffs2
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/padjffs2/src/Makefile b/tools/padjffs2/src/Makefile
new file mode 100644
index 0000000..45da8e5
--- /dev/null
+++ b/tools/padjffs2/src/Makefile
@@ -0,0 +1,15 @@
+CC = gcc
+CFLAGS =
+WFLAGS = -Wall -Werror
+padjffs2-objs = padjffs2.o
+
+all: padjffs2
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(WFLAGS) -c -o $@ $<
+
+padjffs2: $(padjffs2-objs)
+ $(CC) $(LDFLAGS) -o $@ $(padjffs2-objs)
+
+clean:
+ rm -f padjffs2 *.o
diff --git a/tools/padjffs2/src/padjffs2.c b/tools/padjffs2/src/padjffs2.c
new file mode 100644
index 0000000..59c7625
--- /dev/null
+++ b/tools/padjffs2/src/padjffs2.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static char *progname;
+static unsigned int xtra_offset;
+static unsigned char eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
+static unsigned char jffs2_pad_be[] = "\x19\x85\x20\x04\x04\x00\x00\x00\xc4\x94\xdb\xf4";
+static unsigned char jffs2_pad_le[] = "\x85\x19\x04\x20\x00\x00\x00\x04\xa8\xfb\xa0\xb4";
+static unsigned char *pad = eof_mark;
+static int pad_len = sizeof(eof_mark);
+
+#define ERR(fmt, ...) do { \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt "\n", \
+ progname, ## __VA_ARGS__ ); \
+} while (0)
+
+#define ERRS(fmt, ...) do { \
+ int save = errno; \
+ fflush(0); \
+ fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
+ progname, ## __VA_ARGS__, strerror(save)); \
+} while (0)
+
+#define BUF_SIZE (64 * 1024)
+#define ALIGN(_x,_y) (((_x) + ((_y) - 1)) & ~((_y) - 1))
+
+static int pad_image(char *name, uint32_t pad_mask)
+{
+ char *buf;
+ int fd;
+ ssize_t in_len;
+ ssize_t out_len;
+ int ret = -1;
+
+ buf = malloc(BUF_SIZE);
+ if (!buf) {
+ ERR("No memory for buffer");
+ goto out;
+ }
+
+ fd = open(name, O_RDWR);
+ if (fd < 0) {
+ ERRS("Unable to open %s", name);
+ goto free_buf;
+ }
+
+ in_len = lseek(fd, 0, SEEK_END);
+ if (in_len < 0)
+ goto close;
+
+ memset(buf, '\xff', BUF_SIZE);
+
+ in_len += xtra_offset;
+
+ out_len = in_len;
+ while (pad_mask) {
+ uint32_t mask;
+ ssize_t t;
+ int i;
+
+ for (i = 10; i < 32; i++) {
+ mask = 1UL << i;
+ if (pad_mask & mask)
+ break;
+ }
+
+ in_len = ALIGN(in_len, mask);
+
+ for (i = 10; i < 32; i++) {
+ mask = 1UL << i;
+ if ((in_len & (mask - 1)) == 0)
+ pad_mask &= ~mask;
+ }
+
+ printf("padding image to %08x\n", (unsigned int) in_len - xtra_offset);
+
+ while (out_len < in_len) {
+ ssize_t len;
+
+ len = in_len - out_len;
+ if (len > BUF_SIZE)
+ len = BUF_SIZE;
+
+ t = write(fd, buf, len);
+ if (t != len) {
+ ERRS("Unable to write to %s", name);
+ goto close;
+ }
+
+ out_len += len;
+ }
+
+ /* write out the JFFS end-of-filesystem marker */
+ t = write(fd, pad, pad_len);
+ if (t != pad_len) {
+ ERRS("Unable to write to %s", name);
+ goto close;
+ }
+ out_len += pad_len;
+ }
+
+ ret = 0;
+
+close:
+ close(fd);
+free_buf:
+ free(buf);
+out:
+ return ret;
+}
+
+static int usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s file [<options>] [pad0] [pad1] [padN]\n"
+ "Options:\n"
+ " -x <offset>: Add an extra offset for padding data\n"
+ " -J: Use a fake big-endian jffs2 padding element instead of EOF\n"
+ " This is used to work around broken boot loaders that\n"
+ " try to parse the entire firmware area as one big jffs2\n"
+ " -j: (like -J, but little-endian instead of big-endian)\n"
+ "\n",
+ progname);
+ return EXIT_FAILURE;
+}
+
+int main(int argc, char* argv[])
+{
+ char *image;
+ uint32_t pad_mask;
+ int ret = EXIT_FAILURE;
+ int err;
+ int ch, i;
+
+ progname = basename(argv[0]);
+
+ if (argc < 2)
+ return usage();
+
+ image = argv[1];
+ argv++;
+ argc--;
+
+ pad_mask = 0;
+ while ((ch = getopt(argc, argv, "x:Jj")) != -1) {
+ switch (ch) {
+ case 'x':
+ xtra_offset = strtoul(optarg, NULL, 0);
+ fprintf(stderr, "assuming %u bytes offset\n",
+ xtra_offset);
+ break;
+ case 'J':
+ pad = jffs2_pad_be;
+ pad_len = sizeof(jffs2_pad_be) - 1;
+ break;
+ case 'j':
+ pad = jffs2_pad_le;
+ pad_len = sizeof(jffs2_pad_le) - 1;
+ break;
+ default:
+ return usage();
+ }
+ }
+
+ for (i = optind; i < argc; i++)
+ pad_mask |= strtoul(argv[i], NULL, 0) * 1024;
+
+ if (pad_mask == 0)
+ pad_mask = (4 * 1024) | (8 * 1024) | (64 * 1024) |
+ (128 * 1024);
+
+ err = pad_image(image, pad_mask);
+ if (err)
+ goto out;
+
+ ret = EXIT_SUCCESS;
+
+out:
+ return ret;
+}
diff --git a/tools/patch-image/Makefile b/tools/patch-image/Makefile
new file mode 100644
index 0000000..6f2900b
--- /dev/null
+++ b/tools/patch-image/Makefile
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2007-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=patch-image
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(HOSTCC) $(HOST_CFLAGS) -include endian.h -o $(HOST_BUILD_DIR)/patch-cmdline src/patch-cmdline.c
+ $(HOSTCC) $(HOST_CFLAGS) -include endian.h -o $(HOST_BUILD_DIR)/patch-dtb src/patch-dtb.c
+endef
+
+define Host/Install
+ $(CP) $(HOST_BUILD_DIR)/patch-cmdline $(STAGING_DIR_HOST)/bin/
+ $(CP) $(HOST_BUILD_DIR)/patch-dtb $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/patch-cmdline
+ rm -f $(STAGING_DIR_HOST)/bin/patch-dtb
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/patch-image/src/patch-cmdline.c b/tools/patch-image/src/patch-cmdline.c
new file mode 100644
index 0000000..571f848
--- /dev/null
+++ b/tools/patch-image/src/patch-cmdline.c
@@ -0,0 +1,79 @@
+/*
+ * patch-cmdline.c - patch the kernel command line on rb532
+ *
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#define SEARCH_SPACE (16 * 1024)
+#define CMDLINE_MAX 512
+
+int main(int argc, char **argv)
+{
+ int fd, found = 0, len, ret = -1;
+ char *ptr, *p;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <file> <cmdline>\n", argv[0]);
+ goto err1;
+ }
+ len = strlen(argv[2]);
+ if (len + 9 > CMDLINE_MAX) {
+ fprintf(stderr, "Command line string too long\n");
+ goto err1;
+ }
+
+ if (((fd = open(argv[1], O_RDWR)) < 0) ||
+ (ptr = (char *) mmap(0, SEARCH_SPACE + CMDLINE_MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1)) {
+ fprintf(stderr, "Could not open kernel image");
+ goto err2;
+ }
+
+ for (p = ptr; p < (ptr + SEARCH_SPACE); p += 4) {
+ if (memcmp(p, "CMDLINE:", 8) == 0) {
+ found = 1;
+ p += 8;
+ break;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "Command line marker not found!\n");
+ goto err3;
+ }
+
+ memset(p, 0, CMDLINE_MAX - 8);
+ strcpy(p, argv[2]);
+ msync(p, CMDLINE_MAX, MS_SYNC|MS_INVALIDATE);
+ ret = 0;
+
+err3:
+ munmap((void *) ptr, len);
+err2:
+ if (fd > 0)
+ close(fd);
+err1:
+ return ret;
+}
diff --git a/tools/patch-image/src/patch-dtb.c b/tools/patch-image/src/patch-dtb.c
new file mode 100644
index 0000000..161e1dc
--- /dev/null
+++ b/tools/patch-image/src/patch-dtb.c
@@ -0,0 +1,101 @@
+/*
+ * patch-dtb.c - patch a dtb into an image
+ *
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * based on patch-cmdline.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#define SEARCH_SPACE (16 * 1024)
+#define DTB_MAX (16 * 1024)
+
+int main(int argc, char **argv)
+{
+ int fd, fddtb, found = 0, len, ret = -1;
+ char *ptr, *ptrdtb, *p;
+ struct stat s;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <file> <dtb>\n", argv[0]);
+ goto err1;
+ }
+ fddtb = open(argv[1], O_RDONLY);
+ if (!fddtb)
+ goto err1;
+
+ if (stat(argv[2], &s)) {
+ fprintf(stderr, "DTB not found\n");
+ goto err1;
+ }
+
+ len = s.st_size;
+ if (len + 8 > DTB_MAX) {
+ fprintf(stderr, "DTB too big\n");
+ goto err1;
+ }
+
+ if (((fddtb = open(argv[2], O_RDONLY)) < 0) ||
+ (ptrdtb = (char *) mmap(0, DTB_MAX, PROT_READ, MAP_SHARED, fddtb, 0)) == (void *) (-1)) {
+ fprintf(stderr, "Could not open DTB");
+ goto err2;
+ }
+
+ if (((fd = open(argv[1], O_RDWR)) < 0) ||
+ (ptr = (char *) mmap(0, SEARCH_SPACE + DTB_MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1)) {
+ fprintf(stderr, "Could not open kernel image");
+ goto err3;
+ }
+
+ for (p = ptr; p < (ptr + SEARCH_SPACE); p += 4) {
+ if (memcmp(p, "OWRTDTB:", 8) == 0) {
+ found = 1;
+ p += 8;
+ break;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "DTB marker not found!\n");
+ goto err4;
+ }
+
+ memset(p, 0, DTB_MAX - 8);
+ memcpy(p, ptrdtb, len);
+ msync(p, len, MS_SYNC|MS_INVALIDATE);
+ ret = 0;
+
+err4:
+ munmap((void *) ptr, len);
+err3:
+ if (fd > 0)
+ close(fd);
+ munmap((void *) ptrdtb, len);
+err2:
+ if (fddtb > 0)
+ close(fddtb);
+err1:
+ return ret;
+}
diff --git a/tools/patch/Makefile b/tools/patch/Makefile
new file mode 100644
index 0000000..1ea96bf
--- /dev/null
+++ b/tools/patch/Makefile
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=patch
+PKG_VERSION:=2.7.5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/patch
+PKG_MD5SUM:=e3da7940431633fb65a01b91d3b7a27a
+
+HOST_BUILD_PARALLEL := 1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOSTCC := $(HOSTCC_NOCACHE)
+HOSTCXX := $(HOSTCXX_NOCACHE)
+
+$(eval $(call HostBuild))
diff --git a/tools/patchelf/Makefile b/tools/patchelf/Makefile
new file mode 100644
index 0000000..ef8730e
--- /dev/null
+++ b/tools/patchelf/Makefile
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=patchelf
+PKG_VERSION:=0.8
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://nixos.org/releases/patchelf/patchelf-$(PKG_VERSION)
+PKG_MD5SUM:=5b151e3c83b31f5931b4a9fc01635bfd
+
+HOST_BUILD_PARALLEL:=1
+HOST_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/patchelf $(STAGING_DIR_HOST)/bin/patchelf
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/patchelf/patches/100-portability.patch b/tools/patchelf/patches/100-portability.patch
new file mode 100644
index 0000000..04ed8a1
--- /dev/null
+++ b/tools/patchelf/patches/100-portability.patch
@@ -0,0 +1,8 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,4 +1,4 @@
+-AC_INIT([patchelf], m4_esyscmd([echo -n $(cat ./version)]))
++AC_INIT([patchelf], m4_esyscmd([printf $(cat ./version)]))
+ AC_CONFIG_SRCDIR([src/patchelf.cc])
+ AC_CONFIG_AUX_DIR([build-aux])
+ AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2 foreign color-tests parallel-tests])
diff --git a/tools/pkg-config/Makefile b/tools/pkg-config/Makefile
new file mode 100644
index 0000000..40e6e08
--- /dev/null
+++ b/tools/pkg-config/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=pkg-config
+PKG_VERSION:=0.29
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://pkgconfig.freedesktop.org/releases/
+PKG_MD5SUM:=77f27dce7ef88d0634d0d6f90e03a77f
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport PKG_CONFIG
+
+HOST_CONFIGURE_ARGS += --with-internal-glib
+
+ifeq ($(HOST_OS),Darwin)
+HOST_LDFLAGS += -framework CoreFoundation -framework Carbon
+endif
+
+define Host/Install
+ $(MAKE) -C $(HOST_BUILD_DIR) install
+ mv $(STAGING_DIR_HOST)/bin/pkg-config $(STAGING_DIR_HOST)/bin/pkg-config.real
+ $(INSTALL_BIN) ./files/pkg-config $(STAGING_DIR_HOST)/bin/pkg-config
+endef
+
+define Host/Clean
+ -$(MAKE) -C $(HOST_BUILD_DIR) uninstall
+ $(call Host/Clean/Default)
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/pkg-config/files/pkg-config b/tools/pkg-config/files/pkg-config
new file mode 100755
index 0000000..e58b132
--- /dev/null
+++ b/tools/pkg-config/files/pkg-config
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+pkg-config.real $@ --define-variable=prefix=${STAGING_PREFIX} --define-variable=exec_prefix=${STAGING_PREFIX}
diff --git a/tools/ppl/Makefile b/tools/ppl/Makefile
new file mode 100644
index 0000000..082b200
--- /dev/null
+++ b/tools/ppl/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2009-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ppl
+PKG_VERSION:=1.1
+
+PKG_SOURCE_URL:=http://bugseng.com/products/ppl/download/ftp/releases/$(PKG_VERSION)/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_MD5SUM:=82617a9c4e08606111ed9d2dc37ececa
+
+HOST_FIXUP:=autoreconf
+
+HOST_BUILD_PARALLEL:=1
+HOST_CONFIGURE_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport CFLAGS
+
+HOST_CONFIGURE_ARGS += \
+ --enable-static \
+ --disable-shared
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR)/$(3); \
+ $(HOST_CONFIGURE_CMD) \
+ $(HOST_CONFIGURE_VARS) \
+ $(HOST_CONFIGURE_ARGS); \
+ )
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/ppl/patches/001-disable-serial-tests.patch b/tools/ppl/patches/001-disable-serial-tests.patch
new file mode 100644
index 0000000..91b0753
--- /dev/null
+++ b/tools/ppl/patches/001-disable-serial-tests.patch
@@ -0,0 +1,44 @@
+--- a/tests/BD_Shape/Makefile.am
++++ b/tests/BD_Shape/Makefile.am
+@@ -21,8 +21,6 @@
+ # For the most up-to-date information see the Parma Polyhedra Library
+ # site: http://bugseng.com/products/ppl/ .
+
+-AUTOMAKE_OPTIONS = serial-tests
+-
+ if VALGRIND_TESTS_ENABLED
+
+ CHECKER = \
+--- a/tests/Box/Makefile.am
++++ b/tests/Box/Makefile.am
+@@ -21,8 +21,6 @@
+ # For the most up-to-date information see the Parma Polyhedra Library
+ # site: http://bugseng.com/products/ppl/ .
+
+-AUTOMAKE_OPTIONS = serial-tests
+-
+ if VALGRIND_TESTS_ENABLED
+
+ CHECKER = \
+--- a/tests/Concrete_Expression/Makefile.am
++++ b/tests/Concrete_Expression/Makefile.am
+@@ -21,8 +21,6 @@
+ # For the most up-to-date information see the Parma Polyhedra Library
+ # site: http://bugseng.com/products/ppl/ .
+
+-AUTOMAKE_OPTIONS = serial-tests
+-
+ if VALGRIND_TESTS_ENABLED
+
+ CHECKER = \
+--- a/tests/Octagonal_Shape/Makefile.am
++++ b/tests/Octagonal_Shape/Makefile.am
+@@ -21,8 +21,6 @@
+ # For the most up-to-date information see the Parma Polyhedra Library
+ # site: http://bugseng.com/products/ppl/ .
+
+-AUTOMAKE_OPTIONS = serial-tests
+-
+ if VALGRIND_TESTS_ENABLED
+
+ CHECKER = \
diff --git a/tools/qemu/Makefile b/tools/qemu/Makefile
new file mode 100644
index 0000000..bffbaa4
--- /dev/null
+++ b/tools/qemu/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2010-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=qemu
+PKG_VERSION:=0.14.1
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=@SAVANNAH/qemu
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_MD5SUM:=b6c713a8db638e173af53a62d5178640
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CFLAGS += -I$(STAGING_DIR_HOST)/include/e2fsprogs
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR); \
+ CFLAGS="$(HOST_CFLAGS)" \
+ LDFLAGS="$(HOST_LDFLAGS)" \
+ $(HOST_CONFIGURE_CMD) \
+ --extra-cflags="$(HOST_CFLAGS)" \
+ --enable-uuid \
+ )
+endef
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) qemu-img
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/qemu-img $(STAGING_DIR_HOST)/bin
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/quilt/Makefile b/tools/quilt/Makefile
new file mode 100644
index 0000000..939ba69
--- /dev/null
+++ b/tools/quilt/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=quilt
+PKG_VERSION:=0.64
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SAVANNAH/quilt
+PKG_MD5SUM:=fc0310db5868a0873d602d4332a76d43
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Configure
+ cd $(HOST_BUILD_DIR) && autoconf
+ $(call Host/Configure/Default)
+ [ -f $(HOST_BUILD_DIR)/Makefile ]
+endef
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR) SHELL="$(BASH)" all
+endef
+
+define Host/Install
+ $(MAKE) -C $(HOST_BUILD_DIR) SHELL="$(BASH)" install
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/quilt
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/quilt/patches/000-relocatable.patch b/tools/quilt/patches/000-relocatable.patch
new file mode 100644
index 0000000..ed4f00a
--- /dev/null
+++ b/tools/quilt/patches/000-relocatable.patch
@@ -0,0 +1,170 @@
+--- a/bin/quilt.in
++++ b/bin/quilt.in
+@@ -15,14 +15,22 @@ unset POSIXLY_CORRECT
+ unset GREP_OPTIONS
+
+ export TEXTDOMAIN=quilt
+-export TEXTDOMAINDIR=@LOCALEDIR@
+
+-: ${QUILT_DIR=@QUILT_DIR@}
++if test -n "$STAGING_DIR"; then
++ export TEXTDOMAINDIR="$STAGING_DIR/../host/share/locale"
++ : ${QUILT_DIR=$STAGING_DIR/../host/share/quilt} ${QUILT_LIB=$STAGING_DIR/../host/lib/quilt}
++ : ${QUILT_ETC=$STAGING_DIR/../host/etc}
++else
++ export TEXTDOMAINDIR=@LOCALEDIR@
++ : ${QUILT_DIR=@QUILT_DIR@}
++ : ${QUILT_ETC=@ETCDIR@}
++fi
++
+ export QUILT_DIR
+
+ if [ -z "$QUILTRC" ]
+ then
+- for QUILTRC in $HOME/.quiltrc @ETCDIR@/quilt.quiltrc; do
++ for QUILTRC in $HOME/.quiltrc $QUILT_ETC/quilt.quiltrc; do
+ [ -e $QUILTRC ] && break
+ done
+ export QUILTRC
+--- a/quilt/scripts/edmail.in
++++ b/quilt/scripts/edmail.in
+@@ -1,4 +1,6 @@
+-#! @PERL@ -w
++#! @PERL@
++
++use warnings;
+
+ # RFCs important for this script:
+ #
+@@ -29,7 +31,7 @@ BEGIN {
+ }
+
+ setlocale(LC_MESSAGES, "");
+-bindtextdomain("quilt", "@LOCALEDIR@");
++bindtextdomain("quilt", $ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/locale' : "@LOCALEDIR@");
+ textdomain("quilt");
+
+ sub _($) {
+--- a/quilt/scripts/patchfns.in
++++ b/quilt/scripts/patchfns.in
+@@ -8,7 +8,11 @@
+ # See the COPYING and AUTHORS files for more details.
+
+ export TEXTDOMAIN=quilt
+-export TEXTDOMAINDIR=@LOCALEDIR@
++if [ -n "$STAGING_DIR" ]; then
++ export TEXTDOMAINDIR="$STAGING_DIR/../host/share/locale"
++else
++ export TEXTDOMAINDIR=@LOCALEDIR@
++fi
+
+ : ${LC_CTYPE:=$LANG}
+ : ${LC_MESSAGES:=$LANG}
+--- a/quilt/scripts/remove-trailing-ws.in
++++ b/quilt/scripts/remove-trailing-ws.in
+@@ -1,4 +1,6 @@
+-#! @PERL@ -w
++#! @PERL@
++
++use warnings;
+
+ # Remove trailing whitespace from modified lines in working files.
+ #
+@@ -31,7 +33,7 @@ BEGIN {
+ }
+
+ setlocale(LC_MESSAGES, "");
+-bindtextdomain("quilt", "@LOCALEDIR@");
++bindtextdomain("quilt", $ENV{'STAGING_DIR'} ? $ENV{'STAGING_DIR'} . '/../host/share/locale' : "@LOCALEDIR@");
+ textdomain("quilt");
+
+ sub _($) {
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -21,8 +21,8 @@ COLUMN := @COLUMN@
+ GETOPT := @GETOPT@
+ CP := @CP@
+ DATE := @DATE@
+-PERL := @PERL@
+-BASH := @BASH@
++PERL := /usr/bin/env perl
++BASH := /usr/bin/env bash
+ SHELL:= @BASH@ # It does not work if dash is used as a shell, for example
+ GREP := @GREP@
+ TAIL := @TAIL@
+@@ -32,7 +32,7 @@ AWK := @AWK@
+ FIND := @FIND@
+ XARGS := @XARGS@
+ DIFF := @DIFF@
+-PATCH := @PATCH@
++PATCH := /usr/bin/env patch
+ MKTEMP := @MKTEMP@
+ MSGMERGE := @MSGMERGE@
+ MSGFMT := @MSGFMT@
+@@ -48,8 +48,8 @@ USE_NLS := @USE_NLS@
+ STAT_HARDLINK := @STAT_HARDLINK@
+ PATCH_WRAPPER := @PATCH_WRAPPER@
+
+-COMPAT_SYMLINKS := @COMPAT_SYMLINKS@
+-COMPAT_PROGRAMS := @COMPAT_PROGRAMS@
++COMPAT_SYMLINKS :=
++COMPAT_PROGRAMS :=
+
+ default: all
+
+--- a/quilt/scripts/backup-files.in
++++ b/quilt/scripts/backup-files.in
+@@ -53,7 +53,12 @@ usage ()
+ "
+ }
+
+-: ${QUILT_DIR=@QUILT_DIR@}
++if test -n "$STAGING_DIR"; then
++ : ${QUILT_DIR="$STAGING_DIR/../host/share/quilt"}
++else
++ : ${QUILT_DIR=@QUILT_DIR@}
++fi
++
+ . $QUILT_DIR/scripts/utilfns
+
+ ensure_nolinks()
+--- a/bin/guards.in
++++ b/bin/guards.in
+@@ -1,4 +1,6 @@
+-#!@PERL@ -w
++#!@PERL@
++
++use warnings;
+
+ # This script is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License version 2 as
+--- a/compat/date.in
++++ b/compat/date.in
+@@ -1,4 +1,6 @@
+-#! @PERL@ -w
++#! @PERL@
++
++use warnings;
+
+ # This script is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License version 2 as
+--- a/compat/getopt.in
++++ b/compat/getopt.in
+@@ -1,4 +1,6 @@
+-#! @PERL@ -w
++#! @PERL@
++
++use warnings;
+
+ # This script is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License version 2 as
+--- a/quilt/scripts/dependency-graph.in
++++ b/quilt/scripts/dependency-graph.in
+@@ -1,4 +1,6 @@
+-#!@PERL@ -w
++#!@PERL@
++
++use warnings;
+
+ # This script is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License version 2 as
diff --git a/tools/quilt/patches/001-fix_compile.patch b/tools/quilt/patches/001-fix_compile.patch
new file mode 100644
index 0000000..3ce93f0
--- /dev/null
+++ b/tools/quilt/patches/001-fix_compile.patch
@@ -0,0 +1,18 @@
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -271,13 +271,10 @@ $(patsubst %.in,%,$(wildcard bin/*.in qu
+ @$(if $(filter $@,$(NON_EXEC_IN)),,chmod +x $@)
+
+ configure : configure.ac aclocal.m4
+- autoconf
+- @echo "Please run ./configure"
+- @false
++ @touch $@
+
+ Makefile : Makefile.in configure
+- @echo "Please run ./configure"
+- @false
++ @touch $@
+
+ compat_leftover := $(filter-out $(COMPAT),$(shell $(FIND) compat -type f -perm -0100))
+
diff --git a/tools/scons/Makefile b/tools/scons/Makefile
new file mode 100644
index 0000000..bf7559b
--- /dev/null
+++ b/tools/scons/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2011-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=scons
+PKG_VERSION:=2.3.5
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/scons \
+ http://ftp.osuosl.org/pub/blfs/conglomeration/scons/
+PKG_MD5SUM:=8b0d1041266f89b18e47f26d943f8aa5
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Configure
+endef
+
+define Host/Compile
+endef
+
+define Host/Install
+ ./files/pywrap.sh $(HOST_BUILD_DIR)/setup.py install --prefix=$(STAGING_DIR_HOST)
+ rm -f $(STAGING_DIR_HOST)/bin/scons*.py
+ for bin in $(STAGING_DIR_HOST)/bin/scons*; do \
+ mv "$$$$bin" "$$$$bin.py"; \
+ cp ./files/pywrap.sh "$$$$bin"; \
+ done
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/scons/files/pywrap.sh b/tools/scons/files/pywrap.sh
new file mode 100755
index 0000000..f62f590
--- /dev/null
+++ b/tools/scons/files/pywrap.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+case "${0##*/}" in
+ pywrap.sh) arg1="";;
+ *) arg1="$0.py" ;;
+esac
+
+for bin in python python2 python2.7 python2.6 python2.5 python2.4; do
+ case "$($bin -V 2>&1)" in
+ "Python 2"*) exec $bin $arg1 "$@" ;;
+ esac
+done
+
+echo "Unable to find a Python 2.x interpreter for executing ${arg1:+$arg1 }$@ !" >&2
+exit 1
diff --git a/tools/scons/patches/001-platform_env.patch b/tools/scons/patches/001-platform_env.patch
new file mode 100644
index 0000000..8aab904
--- /dev/null
+++ b/tools/scons/patches/001-platform_env.patch
@@ -0,0 +1,11 @@
+--- a/engine/SCons/Platform/__init__.py
++++ b/engine/SCons/Platform/__init__.py
+@@ -63,6 +63,8 @@ def platform_default():
+ care about the machine architecture.
+ """
+ osname = os.name
++ if 'PLATFORM' in os.environ:
++ return os.environ['PLATFORM']
+ if osname == 'java':
+ osname = os._osType
+ if osname == 'posix':
diff --git a/tools/sdimage/Makefile b/tools/sdimage/Makefile
new file mode 100644
index 0000000..e590417
--- /dev/null
+++ b/tools/sdimage/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=imx-uuc
+PKG_VERSION=2015-09-13-$(PKG_SOURCE_VERSION)
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/mhei/fsl-imx-uuc.git
+PKG_SOURCE_VERSION:=2b99403b6dc60a22b07eb7a5cc0cb184abb89bdd
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_SOURCE_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.bz2
+
+PKG_LICENSE:=GPL-2.0+
+PKG_LICENSE_FILES:=LICENSE
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_SOURCE_SUBDIR)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Configure
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/sdimage $(STAGING_DIR_HOST)/bin/sdimage
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/sdimage
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/sed/Makefile b/tools/sed/Makefile
new file mode 100644
index 0000000..0e130e2
--- /dev/null
+++ b/tools/sed/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2006-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sed
+PKG_VERSION:=4.2.2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
+PKG_MD5SUM:=7ffe1c7cdc3233e1e0c4b502df253974
+PKG_CAT:=bzcat
+export SED:=
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += \
+ --disable-acl \
+ --disable-nls \
+
+HOST_CONFIGURE_VARS += \
+ ac_cv_search_setfilecon=no \
+ ac_cv_header_selinux_context_h=no \
+ ac_cv_header_selinux_selinux_h=no \
+
+define Host/Compile
+ +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR) SHELL="$(BASH)"
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/sed/sed $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/sed
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/sed/patches/001-musl_host_fixup.patch b/tools/sed/patches/001-musl_host_fixup.patch
new file mode 100644
index 0000000..4dcb1ec
--- /dev/null
+++ b/tools/sed/patches/001-musl_host_fixup.patch
@@ -0,0 +1,24 @@
+--- a/build-aux/config.sub
++++ b/build-aux/config.sub
+@@ -122,9 +122,9 @@ esac
+ # Here we must recognize all the valid KERNEL-OS combinations.
+ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+ case $maybe_os in
+- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+- knetbsd*-gnu* | netbsd*-gnu* | \
++ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-musl* | \
++ linux-newlib* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
++ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+@@ -1360,7 +1360,7 @@ case $os in
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-android* \
+- | -linux-newlib* | -linux-uclibc* \
++ | -linux-musl* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff --git a/tools/sparse/Makefile b/tools/sparse/Makefile
new file mode 100644
index 0000000..6cdeed5
--- /dev/null
+++ b/tools/sparse/Makefile
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2014 Qualcomm-Atheros Inc.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sparse
+PKG_VERSION:=0.5.0
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@KERNEL/software/devel/sparse/dist/
+PKG_MD5SUM:=68bc834c57836251fbee55a7707bab39
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/sparse $(STAGING_DIR_HOST)/bin
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/squashfs/Makefile b/tools/squashfs/Makefile
new file mode 100644
index 0000000..88416bd
--- /dev/null
+++ b/tools/squashfs/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=squashfs
+PKG_VERSION:=3.0
+
+PKG_SOURCE:=$(PKG_NAME)$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/squashfs
+PKG_MD5SUM:=9fd05d0bfbb712f5fb95edafea5bc733
+PKG_CAT:=zcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR)/squashfs-tools \
+ CC="$(HOSTCC)" \
+ CXX="$(CXX)" \
+ LZMAPATH=$(STAGING_DIR_HOST)/lib \
+ mksquashfs-lzma unsquashfs-lzma
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/squashfs-tools/mksquashfs-lzma $(STAGING_DIR_HOST)/bin/
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/squashfs-tools/unsquashfs-lzma $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mksquashfs-lzma
+ rm -f $(STAGING_DIR_HOST)/bin/unsquashfs-lzma
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/squashfs/patches/100-lzma.patch b/tools/squashfs/patches/100-lzma.patch
new file mode 100644
index 0000000..e3b2a3a
--- /dev/null
+++ b/tools/squashfs/patches/100-lzma.patch
@@ -0,0 +1,22 @@
+--- a/squashfs-tools/Makefile
++++ b/squashfs-tools/Makefile
+@@ -7,6 +8,9 @@ all: mksquashfs unsquashfs
+ mksquashfs: mksquashfs.o read_fs.o sort.o
+ $(CC) mksquashfs.o read_fs.o sort.o -lz -o $@
+
++mksquashfs-lzma: mksquashfs.o read_fs.o sort.o
++ $(CXX) mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -llzma-old -o $@
++
+ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h
+
+ read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h
+@@ -16,4 +20,9 @@ sort.o: sort.c squashfs_fs.h global.h so
+ unsquashfs: unsquashfs.o
+ $(CC) unsquashfs.o -lz -o $@
+
++unsquashfs-lzma: unsquashfs.o
++ $(CXX) unsquashfs.o -L$(LZMAPATH) -llzma-old -o $@
++
+ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h
++
++clean:
diff --git a/tools/squashfs/patches/110-no_nonstatic_inline.patch b/tools/squashfs/patches/110-no_nonstatic_inline.patch
new file mode 100644
index 0000000..8e288f3
--- /dev/null
+++ b/tools/squashfs/patches/110-no_nonstatic_inline.patch
@@ -0,0 +1,11 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -1347,7 +1347,7 @@ struct inode_info *lookup_inode(struct s
+ }
+
+
+-inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir)
++static inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir)
+ {
+ if((dir->count % DIR_ENTRIES) == 0)
+ if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL)
diff --git a/tools/squashfs4/Makefile b/tools/squashfs4/Makefile
new file mode 100644
index 0000000..50b70fb
--- /dev/null
+++ b/tools/squashfs4/Makefile
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=squashfs4
+PKG_VERSION:=4.2
+
+PKG_SOURCE:=squashfs$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=@SF/squashfs
+PKG_MD5SUM:=1b7a781fb4cf8938842279bd3e8ee852
+PKG_CAT:=zcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/squashfs$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR)/squashfs-tools \
+ CC="$(HOSTCC)" \
+ XZ_SUPPORT=1 \
+ LZMA_XZ_SUPPORT=1 \
+ XATTR_SUPPORT= \
+ LZMA_LIB="$(STAGING_DIR_HOST)/lib/liblzma.a" \
+ EXTRA_CFLAGS="-I$(STAGING_DIR_HOST)/include" \
+ mksquashfs unsquashfs
+endef
+
+define Host/Install
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/squashfs-tools/mksquashfs $(STAGING_DIR_HOST)/bin/mksquashfs4
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/squashfs-tools/unsquashfs $(STAGING_DIR_HOST)/bin/unsquashfs4
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mksquashfs4
+ rm -f $(STAGING_DIR_HOST)/bin/unsquashfs4
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/squashfs4/patches/100-portability.patch b/tools/squashfs4/patches/100-portability.patch
new file mode 100644
index 0000000..ac1349c
--- /dev/null
+++ b/tools/squashfs4/patches/100-portability.patch
@@ -0,0 +1,40 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -60,6 +60,10 @@
+ #include <sys/sysinfo.h>
+ #endif
+
++#ifndef FNM_EXTMATCH
++#define FNM_EXTMATCH 0
++#endif
++
+ #ifdef SQUASHFS_TRACE
+ #define TRACE(s, args...) \
+ do { \
+--- a/squashfs-tools/unsquashfs.h
++++ b/squashfs-tools/unsquashfs.h
+@@ -49,8 +49,14 @@
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
++#include <sys/sysctl.h>
+ #else
+ #include <endian.h>
++#include <sys/sysinfo.h>
++#endif
++
++#ifndef FNM_EXTMATCH
++#define FNM_EXTMATCH 0
+ #endif
+
+ #include "squashfs_fs.h"
+--- a/squashfs-tools/unsquashfs.c
++++ b/squashfs-tools/unsquashfs.c
+@@ -29,7 +29,6 @@
+ #include "compressor.h"
+ #include "xattr.h"
+
+-#include <sys/sysinfo.h>
+ #include <sys/types.h>
+
+ struct cache *fragment_cache, *data_cache;
diff --git a/tools/squashfs4/patches/110-allow_static_liblzma.patch b/tools/squashfs4/patches/110-allow_static_liblzma.patch
new file mode 100644
index 0000000..9a3a744
--- /dev/null
+++ b/tools/squashfs4/patches/110-allow_static_liblzma.patch
@@ -0,0 +1,30 @@
+--- a/squashfs-tools/Makefile
++++ b/squashfs-tools/Makefile
+@@ -129,7 +129,6 @@ ifeq ($(LZMA_XZ_SUPPORT),1)
+ CFLAGS += -DLZMA_SUPPORT
+ MKSQUASHFS_OBJS += lzma_xz_wrapper.o
+ UNSQUASHFS_OBJS += lzma_xz_wrapper.o
+-LIBS += -llzma
+ COMPRESSORS += lzma
+ endif
+
+@@ -137,10 +136,18 @@ ifeq ($(XZ_SUPPORT),1)
+ CFLAGS += -DXZ_SUPPORT
+ MKSQUASHFS_OBJS += xz_wrapper.o
+ UNSQUASHFS_OBJS += xz_wrapper.o
+-LIBS += -llzma
+ COMPRESSORS += xz
+ endif
+
++ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),)
++ifneq ($(LZMA_LIB),)
++MKSQUASHFS_OBJS += $(LZMA_LIB)
++UNSQUASHFS_OBJS += $(LZMA_LIB)
++else
++LIBS += -llzma
++endif
++endif
++
+ ifeq ($(LZO_SUPPORT),1)
+ CFLAGS += -DLZO_SUPPORT
+ ifdef LZO_DIR
diff --git a/tools/squashfs4/patches/120-cygwin_fixes.patch b/tools/squashfs4/patches/120-cygwin_fixes.patch
new file mode 100644
index 0000000..fa1dfba
--- /dev/null
+++ b/tools/squashfs4/patches/120-cygwin_fixes.patch
@@ -0,0 +1,153 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -51,15 +51,22 @@
+ #include <sys/wait.h>
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
+ #include <sys/sysctl.h>
++#endif /* __CYGWIN__ */
+ #else
+ #include <endian.h>
+ #include <sys/sysinfo.h>
+ #endif
+
++#ifdef __CYGWIN__
++#include <sys/termios.h>
++#define FNM_EXTMATCH (1 << 5)
++#endif
++
+ #ifndef FNM_EXTMATCH
+ #define FNM_EXTMATCH 0
+ #endif
+@@ -844,6 +851,7 @@ void sigusr1_handler()
+
+ void sigwinch_handler()
+ {
++#ifndef __CYGWIN__
+ struct winsize winsize;
+
+ if(ioctl(1, TIOCGWINSZ, &winsize) == -1) {
+@@ -853,6 +861,9 @@ void sigwinch_handler()
+ columns = 80;
+ } else
+ columns = winsize.ws_col;
++#else
++ columns = 80;
++#endif
+ }
+
+
+@@ -4066,6 +4077,9 @@ void initialise_threads(int readb_mbytes
+
+ signal(SIGUSR1, sigusr1_handler);
+
++#ifdef __CYGWIN__
++ processors = atoi(getenv("NUMBER_OF_PROCESSORS"));
++#else
+ if(processors == -1) {
+ #ifndef linux
+ int mib[2];
+@@ -4087,6 +4101,7 @@ void initialise_threads(int readb_mbytes
+ processors = sysconf(_SC_NPROCESSORS_ONLN);
+ #endif
+ }
++#endif /* __CYGWIN__ */
+
+ thread = malloc((2 + processors * 2) * sizeof(pthread_t));
+ if(thread == NULL)
+--- a/squashfs-tools/read_fs.c
++++ b/squashfs-tools/read_fs.c
+@@ -33,9 +33,11 @@
+ #include <sys/mman.h>
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
++#endif
+ #else
+ #include <endian.h>
+ #endif
+--- a/squashfs-tools/swap.c
++++ b/squashfs-tools/swap.c
+@@ -20,9 +20,11 @@
+ */
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
++#endif
+ #else
+ #include <endian.h>
+ #endif
+--- a/squashfs-tools/unsquashfs.c
++++ b/squashfs-tools/unsquashfs.c
+@@ -117,6 +117,7 @@ void update_progress_bar();
+
+ void sigwinch_handler()
+ {
++#ifndef __CYGWIN__
+ struct winsize winsize;
+
+ if(ioctl(1, TIOCGWINSZ, &winsize) == -1) {
+@@ -126,6 +127,9 @@ void sigwinch_handler()
+ columns = 80;
+ } else
+ columns = winsize.ws_col;
++#else
++ columns = 80;
++#endif
+ }
+
+
+@@ -1807,7 +1811,9 @@ void initialise_threads(int fragment_buf
+ if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1)
+ EXIT_UNSQUASH("Failed to set signal mask in intialise_threads"
+ "\n");
+-
++#ifdef __CYGWIN__
++ processors = atoi(getenv("NUMBER_OF_PROCESSORS"));
++#else
+ if(processors == -1) {
+ #ifndef linux
+ int mib[2];
+@@ -1829,6 +1835,7 @@ void initialise_threads(int fragment_buf
+ processors = sysconf(_SC_NPROCESSORS_ONLN);
+ #endif
+ }
++#endif /* __CYGWIN__ */
+
+ thread = malloc((3 + processors) * sizeof(pthread_t));
+ if(thread == NULL)
+--- a/squashfs-tools/unsquashfs.h
++++ b/squashfs-tools/unsquashfs.h
+@@ -46,15 +46,22 @@
+ #include <sys/time.h>
+
+ #ifndef linux
++#ifndef __CYGWIN__
+ #define __BYTE_ORDER BYTE_ORDER
+ #define __BIG_ENDIAN BIG_ENDIAN
+ #define __LITTLE_ENDIAN LITTLE_ENDIAN
+ #include <sys/sysctl.h>
++#endif
+ #else
+ #include <endian.h>
+ #include <sys/sysinfo.h>
+ #endif
+
++#ifdef __CYGWIN__
++#include <sys/termios.h>
++#define FNM_EXTMATCH (1 << 5)
++#endif
++
+ #ifndef FNM_EXTMATCH
+ #define FNM_EXTMATCH 0
+ #endif
diff --git a/tools/squashfs4/patches/150-freebsd_fixes.patch b/tools/squashfs4/patches/150-freebsd_fixes.patch
new file mode 100644
index 0000000..44d40a7
--- /dev/null
+++ b/tools/squashfs4/patches/150-freebsd_fixes.patch
@@ -0,0 +1,10 @@
+--- a/squashfs-tools/pseudo.c
++++ b/squashfs-tools/pseudo.c
+@@ -32,6 +32,7 @@
+ #include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
++#include <sys/stat.h>
+
+ #include "pseudo.h"
+
diff --git a/tools/squashfs4/patches/160-expose_lzma_xz_options.patch b/tools/squashfs4/patches/160-expose_lzma_xz_options.patch
new file mode 100644
index 0000000..d606396
--- /dev/null
+++ b/tools/squashfs4/patches/160-expose_lzma_xz_options.patch
@@ -0,0 +1,929 @@
+--- /dev/null
++++ b/squashfs-tools/lzma_xz_options.h
+@@ -0,0 +1,115 @@
++#ifndef LZMA_XZ_OPTIONS_H
++#define LZMA_XZ_OPTIONS_H
++/*
++ * Copyright (c) 2011
++ * Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * 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,
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * lzma_options.h
++ */
++
++#include <stdint.h>
++
++#ifndef linux
++#ifdef __FreeBSD__
++#include <machine/endian.h>
++#endif
++#define __BYTE_ORDER BYTE_ORDER
++#define __BIG_ENDIAN BIG_ENDIAN
++#define __LITTLE_ENDIAN LITTLE_ENDIAN
++#else
++#include <endian.h>
++#endif
++
++
++
++struct lzma_opts {
++ uint32_t flags;
++#define LZMA_OPT_FLT_MASK 0xffff
++#define LZMA_OPT_PRE_OFF 16
++#define LZMA_OPT_PRE_MASK (0xf << LZMA_OPT_PRE_OFF)
++#define LZMA_OPT_EXTREME 20
++ uint16_t bit_opts;
++#define LZMA_OPT_LC_OFF 0
++#define LZMA_OPT_LC_MASK (0x7 << LZMA_OPT_LC_OFF)
++#define LZMA_OPT_LP_OFF 3
++#define LZMA_OPT_LP_MASK (0x7 << LZMA_OPT_LP_OFF)
++#define LZMA_OPT_PB_OFF 6
++#define LZMA_OPT_PB_MASK (0x7 << LZMA_OPT_PB_OFF)
++ uint16_t fb;
++ uint32_t dict_size;
++};
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++extern unsigned int inswap_le32(unsigned int);
++
++#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s) { \
++ (s)->flags = inswap_le32((s)->flags); \
++ (s)->bit_opts = inswap_le16((s)->bit_opts); \
++ (s)->fb = inswap_le16((s)->fb); \
++ (s)->dict_size = inswap_le32((s)->dict_size); \
++}
++#else
++#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s)
++#endif
++
++#define MEMLIMIT (32 * 1024 * 1024)
++
++#define LZMA_OPT_LC_MIN 0
++#define LZMA_OPT_LC_MAX 4
++#define LZMA_OPT_LC_DEFAULT 3
++
++#define LZMA_OPT_LP_MIN 0
++#define LZMA_OPT_LP_MAX 4
++#define LZMA_OPT_LP_DEFAULT 0
++
++#define LZMA_OPT_PB_MIN 0
++#define LZMA_OPT_PB_MAX 4
++#define LZMA_OPT_PB_DEFAULT 2
++
++#define LZMA_OPT_FB_MIN 5
++#define LZMA_OPT_FB_MAX 273
++#define LZMA_OPT_FB_DEFAULT 64
++
++enum {
++ LZMA_OPT_LZMA = 1,
++ LZMA_OPT_XZ
++};
++
++struct lzma_xz_options {
++ int preset;
++ int extreme;
++ int lc;
++ int lp;
++ int pb;
++ int fb;
++ int dict_size;
++ int flags;
++};
++
++struct lzma_xz_options *lzma_xz_get_options(void);
++
++int lzma_xz_options(char *argv[], int argc, int lzmaver);
++
++int lzma_xz_options_post(int block_size, int lzmaver);
++
++void *lzma_xz_dump_options(int block_size, int *size, int flags);
++
++int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver);
++
++void lzma_xz_usage(int lzmaver);
++
++#endif
+--- /dev/null
++++ b/squashfs-tools/lzma_xz_options.c
+@@ -0,0 +1,365 @@
++/*
++ * Copyright (c) 2011
++ * Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * 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,
++ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * lzma_options.c
++ *
++ * Common options for LZMA1 and 2 compressors. Based on xz_wrapper.c
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++
++#include <lzma.h>
++
++#include "lzma_xz_options.h"
++
++static const char const *lzmaver_str[] = { "", "lzma", "xz" };
++
++static struct lzma_xz_options options = {
++ .flags = 0,
++ .preset = 6,
++ .extreme = 0,
++ .lc = LZMA_OPT_LC_DEFAULT,
++ .lp = LZMA_OPT_LP_DEFAULT,
++ .pb = LZMA_OPT_PB_DEFAULT,
++ .fb = LZMA_OPT_FB_DEFAULT,
++ .dict_size = 0,
++};
++
++static float lzma_dict_percent = 0;
++
++struct lzma_xz_options *lzma_xz_get_options(void)
++{
++ return &options;
++}
++
++
++int lzma_xz_options(char *argv[], int argc, int lzmaver)
++{
++ const char *comp_name = lzmaver_str[lzmaver];
++
++ if(strcmp(argv[0], "-Xpreset") == 0) {
++ int preset;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xpreset missing preset\n", comp_name);
++ goto failed;
++ }
++
++ preset = atoi(argv[1]);
++
++ if (preset < 0 || preset > 9) {
++ fprintf(stderr, "%s: -Xpreset invalid value\n", comp_name);
++ goto failed;
++ }
++ options.preset = preset;
++ return 1;
++ } else if(strcmp(argv[0], "-Xe") == 0) {
++ options.extreme = 1;
++ return 0;
++ } else if(strcmp(argv[0], "-Xlc") == 0) {
++ int lc;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xlc missing lc\n", comp_name);
++ goto failed;
++ }
++
++ lc = atoi(argv[1]);
++
++ if (lc < LZMA_OPT_LC_MIN || lc > LZMA_OPT_LC_MAX) {
++ fprintf(stderr, "%s: -Xlc invalid value\n", comp_name);
++ goto failed;
++ }
++ options.lc = lc;
++ return 1;
++ } else if(strcmp(argv[0], "-Xlp") == 0) {
++ int lp;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xlp missing lp\n", comp_name);
++ goto failed;
++ }
++
++ lp = atoi(argv[1]);
++
++ if (lp < LZMA_OPT_LP_MIN || lp > LZMA_OPT_LP_MAX) {
++ fprintf(stderr, "%s: -Xlp invalid value\n", comp_name);
++ goto failed;
++ }
++ options.lp = lp;
++ return 1;
++ } else if(strcmp(argv[0], "-Xpb") == 0) {
++ int pb;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xpb missing pb\n", comp_name);
++ goto failed;
++ }
++
++ pb = atoi(argv[1]);
++
++ if (pb < LZMA_OPT_PB_MIN || pb > LZMA_OPT_PB_MAX) {
++ fprintf(stderr, "%s: -Xbp invalid value\n", comp_name);
++ goto failed;
++ }
++ options.pb = pb;
++ return 1;
++ } else if(strcmp(argv[0], "-Xfb") == 0) {
++ int fb;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xfb missing fb\n", comp_name);
++ goto failed;
++ }
++
++ fb = atoi(argv[1]);
++
++ if (fb < LZMA_OPT_FB_MIN || fb > LZMA_OPT_FB_MAX) {
++ fprintf(stderr, "%s: -Xfb invalid value\n", comp_name);
++ goto failed;
++ }
++ options.fb = fb;
++ return 1;
++ } else if(strcmp(argv[0], "-Xdict-size") == 0) {
++ char *b;
++ float size;
++
++ if(argc < 2) {
++ fprintf(stderr, "%s: -Xdict-size missing dict-size\n", comp_name);
++ goto failed;
++ }
++
++ size = strtof(argv[1], &b);
++ if(*b == '%') {
++ if(size <= 0 || size > 100) {
++ fprintf(stderr, "%s: -Xdict-size percentage "
++ "should be 0 < dict-size <= 100\n", comp_name);
++ goto failed;
++ }
++
++ lzma_dict_percent = size;
++ options.dict_size = 0;
++ } else {
++ if((float) ((int) size) != size) {
++ fprintf(stderr, "%s: -Xdict-size can't be "
++ "fractional unless a percentage of the"
++ " block size\n", comp_name);
++ goto failed;
++ }
++
++ lzma_dict_percent = 0;
++ options.dict_size = (int) size;
++
++ if(*b == 'k' || *b == 'K')
++ options.dict_size *= 1024;
++ else if(*b == 'm' || *b == 'M')
++ options.dict_size *= 1024 * 1024;
++ else if(*b != '\0') {
++ fprintf(stderr, "%s: -Xdict-size invalid "
++ "dict-size\n", comp_name);
++ goto failed;
++ }
++ }
++
++ return 1;
++ }
++
++ return -1;
++
++failed:
++ return -2;
++
++}
++
++int lzma_xz_options_post(int block_size, int lzmaver)
++{
++ const char *comp_name = lzmaver_str[lzmaver];
++ /*
++ * if -Xdict-size has been specified use this to compute the datablock
++ * dictionary size
++ */
++ if(options.dict_size || lzma_dict_percent) {
++ int dict_size_min = (lzmaver == 1 ? 4096 : 8192);
++ int n;
++
++ if(options.dict_size) {
++ if(options.dict_size > block_size) {
++ fprintf(stderr, "%s: -Xdict-size is larger than"
++ " block_size\n", comp_name);
++ goto failed;
++ }
++ } else
++ options.dict_size = block_size * lzma_dict_percent / 100;
++
++ if(options.dict_size < dict_size_min) {
++ fprintf(stderr, "%s: -Xdict-size should be %i bytes "
++ "or larger\n", comp_name, dict_size_min);
++ goto failed;
++ }
++
++ /*
++ * dictionary_size must be storable in xz header as either
++ * 2^n or as 2^n+2^(n+1)
++ */
++ n = ffs(options.dict_size) - 1;
++ if(options.dict_size != (1 << n) &&
++ options.dict_size != ((1 << n) + (1 << (n + 1)))) {
++ fprintf(stderr, "%s: -Xdict-size is an unsupported "
++ "value, dict-size must be storable in %s "
++ "header\n", comp_name, comp_name);
++ fprintf(stderr, "as either 2^n or as 2^n+2^(n+1). "
++ "Example dict-sizes are 75%%, 50%%, 37.5%%, "
++ "25%%,\n");
++ fprintf(stderr, "or 32K, 16K, 8K etc.\n");
++ goto failed;
++ }
++
++ } else
++ /* No -Xdict-size specified, use defaults */
++ options.dict_size = block_size;
++
++ return 0;
++
++failed:
++ return -1;
++}
++
++static struct lzma_opts lzma_comp_opts;
++
++void *lzma_xz_dump_options(int block_size, int *size, int flags)
++{
++ /* No need to store default options */
++ if (options.preset == 6 &&
++ options.extreme == 0 &&
++ options.lc == LZMA_OPT_LC_DEFAULT &&
++ options.lp == LZMA_OPT_LC_DEFAULT &&
++ options.pb == LZMA_OPT_PB_DEFAULT &&
++ options.fb == 0 &&
++ options.dict_size == block_size &&
++ flags == 0)
++ return NULL;
++
++ *size = sizeof(struct lzma_opts);
++
++ lzma_comp_opts.flags |= flags;
++
++ if (options.extreme)
++ lzma_comp_opts.flags |= LZMA_OPT_EXTREME;
++
++ lzma_comp_opts.flags |= ((options.preset << LZMA_OPT_PRE_OFF) & LZMA_OPT_PRE_MASK);
++
++ lzma_comp_opts.bit_opts =
++ ((options.lc << LZMA_OPT_LC_OFF) & LZMA_OPT_LC_MASK) |
++ ((options.lp << LZMA_OPT_LP_OFF) & LZMA_OPT_LP_MASK) |
++ ((options.pb << LZMA_OPT_PB_OFF) & LZMA_OPT_PB_MASK);
++ lzma_comp_opts.fb = options.fb;
++ lzma_comp_opts.dict_size = options.dict_size;
++
++ SQUASHFS_INSWAP_LZMA_COMP_OPTS(&lzma_comp_opts);
++
++ return &lzma_comp_opts;
++}
++
++int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver)
++{
++ if (size == 0) {
++ /* default options */
++ options.preset = 6;
++ options.extreme = 0;
++ options.lc = LZMA_OPT_LC_DEFAULT;
++ options.lp = LZMA_OPT_LC_DEFAULT;
++ options.pb = LZMA_OPT_PB_DEFAULT;
++ options.fb = LZMA_OPT_FB_DEFAULT;
++ options.dict_size = block_size;
++ options.flags = 0;
++ } else {
++ struct lzma_opts *comp_opts = buffer;
++ int n;
++
++ if (size != sizeof(struct lzma_opts))
++ goto failed;
++
++ SQUASHFS_INSWAP_LZMA_COMP_OPTS(comp_opts);
++
++ options.flags = comp_opts->flags & LZMA_OPT_FLT_MASK;
++ options.preset = (comp_opts->flags & LZMA_OPT_PRE_MASK) >> LZMA_OPT_PRE_OFF;
++ options.extreme = !!(comp_opts->flags & LZMA_OPT_EXTREME);
++
++ options.lc = (comp_opts->bit_opts & LZMA_OPT_LC_MASK) >> LZMA_OPT_LC_OFF;
++ options.lp = (comp_opts->bit_opts & LZMA_OPT_LP_MASK) >> LZMA_OPT_LP_OFF;
++ options.pb = (comp_opts->bit_opts & LZMA_OPT_PB_MASK) >> LZMA_OPT_PB_OFF;
++ options.fb = comp_opts->fb;
++ options.dict_size = comp_opts->dict_size;
++
++ /* check that the LZMA bit options are in range */
++ if (options.lc < LZMA_OPT_LC_MIN || options.lc > LZMA_OPT_LC_MAX ||
++ options.lp < LZMA_OPT_LP_MIN || options.lp > LZMA_OPT_LP_MAX ||
++ options.pb < LZMA_OPT_PB_MIN || options.pb > LZMA_OPT_PB_MAX ||
++ options.fb < LZMA_OPT_FB_MIN || options.fb > LZMA_OPT_FB_MAX)
++ goto failed;
++
++ /*
++ * check that the dictionary size seems correct - the dictionary
++ * size should 2^n or 2^n+2^(n+1)
++ */
++ n = ffs(options.dict_size) - 1;
++ if(options.dict_size != (1 << n) &&
++ options.dict_size != ((1 << n) + (1 << (n + 1))))
++ goto failed;
++
++ }
++
++ return 0;
++
++failed:
++ fprintf(stderr, "%s: error reading stored compressor options from "
++ "filesystem!\n", lzmaver_str[lzmaver]);
++ return -1;
++}
++
++void lzma_xz_usage(int lzmaver)
++{
++ fprintf(stderr, "\t -Xpreset <preset>\n");
++ fprintf(stderr, "\t\tcompression preset (0-9, default 6)\n");
++ fprintf(stderr, "\t -Xe\n");
++ fprintf(stderr, "\t\tTry to improve compression ratio by using more ");
++ fprintf(stderr, "CPU time.\n");
++ fprintf(stderr, "\t -Xlc <lc>\n");
++ fprintf(stderr, "\t\tNumber of literal context bits (0-4, default 3)\n");
++ fprintf(stderr, "\t -Xlp <lp>\n");
++ fprintf(stderr, "\t\tNumber of literal position bits (0-4, default 0)\n");
++ fprintf(stderr, "\t -Xpb <pb>\n");
++ fprintf(stderr, "\t\tNumber of position bits (0-4, default 2)\n");
++ fprintf(stderr, "\t -Xnice <nice>\n");
++ fprintf(stderr, "\t\tNice length of a match (5-273, default 64)\n");
++ fprintf(stderr, "\t -Xdict-size <dict-size>\n");
++ fprintf(stderr, "\t\tUse <dict-size> as the %s dictionary size. The",
++ lzmaver == LZMA_OPT_LZMA ? "LZMA" : "XZ");
++ fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
++ fprintf(stderr, " percentage of the block size, or as an\n\t\t");
++ fprintf(stderr, "absolute value. The dictionary size must be less");
++ fprintf(stderr, " than or equal\n\t\tto the block size and %d bytes",
++ lzmaver == LZMA_OPT_LZMA ? 4096 : 8192);
++ fprintf(stderr, " or larger. It must also be\n\t\tstorable in the lzma");
++ fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
++ fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
++ fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
++
++}
+--- a/squashfs-tools/lzma_xz_wrapper.c
++++ b/squashfs-tools/lzma_xz_wrapper.c
+@@ -27,6 +27,7 @@
+
+ #include "squashfs_fs.h"
+ #include "compressor.h"
++#include "lzma_xz_options.h"
+
+ #define LZMA_PROPS_SIZE 5
+ #define LZMA_UNCOMP_SIZE 8
+@@ -38,13 +39,27 @@
+ static int lzma_compress(void *dummy, void *dest, void *src, int size,
+ int block_size, int *error)
+ {
++ uint32_t preset;
+ unsigned char *d = (unsigned char *) dest;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
++
+ lzma_options_lzma opt;
+ lzma_stream strm = LZMA_STREAM_INIT;
+ int res;
+
+- lzma_lzma_preset(&opt, LZMA_OPTIONS);
+- opt.dict_size = block_size;
++ preset = opts->preset;
++
++ if (opts->extreme)
++ preset |= LZMA_PRESET_EXTREME;
++
++ lzma_lzma_preset(&opt, opts->preset);
++ opt.lc = opts->lc;
++ opt.lp = opts->lp;
++ opt.pb = opts->pb;
++ if (opts->fb)
++ opt.nice_len = opts->fb;
++
++ opt.dict_size = opts->dict_size;
+
+ res = lzma_alone_encoder(&strm, &opt);
+ if(res != LZMA_OK) {
+@@ -143,13 +158,45 @@ failed:
+ return -1;
+ }
+
++static int lzma_options(char *argv[], int argc)
++{
++ return lzma_xz_options(argv, argc, LZMA_OPT_LZMA);
++}
++
++
++static int lzma_options_post(int block_size)
++{
++ return lzma_xz_options_post(block_size, LZMA_OPT_LZMA);
++}
++
++
++static void *lzma_dump_options(int block_size, int *size)
++{
++ return lzma_xz_dump_options(block_size, size, 0);
++}
++
++
++static int lzma_extract_options(int block_size, void *buffer, int size)
++{
++ return lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_LZMA);
++}
++
++
++void lzma_usage()
++{
++ lzma_xz_usage(LZMA_OPT_LZMA);
++}
++
+
+ struct compressor lzma_comp_ops = {
+ .init = NULL,
+ .compress = lzma_compress,
+ .uncompress = lzma_uncompress,
+- .options = NULL,
+- .usage = NULL,
++ .options = lzma_options,
++ .options_post = lzma_options_post,
++ .dump_options = lzma_dump_options,
++ .extract_options = lzma_extract_options,
++ .usage = lzma_usage,
+ .id = LZMA_COMPRESSION,
+ .name = "lzma",
+ .supported = 1
+--- a/squashfs-tools/xz_wrapper.h
++++ b/squashfs-tools/xz_wrapper.h
+@@ -24,25 +24,6 @@
+ *
+ */
+
+-#ifndef linux
+-#define __BYTE_ORDER BYTE_ORDER
+-#define __BIG_ENDIAN BIG_ENDIAN
+-#define __LITTLE_ENDIAN LITTLE_ENDIAN
+-#else
+-#include <endian.h>
+-#endif
+-
+-#if __BYTE_ORDER == __BIG_ENDIAN
+-extern unsigned int inswap_le32(unsigned int);
+-
+-#define SQUASHFS_INSWAP_COMP_OPTS(s) { \
+- (s)->dictionary_size = inswap_le32((s)->dictionary_size); \
+- (s)->flags = inswap_le32((s)->flags); \
+-}
+-#else
+-#define SQUASHFS_INSWAP_COMP_OPTS(s)
+-#endif
+-
+ #define MEMLIMIT (32 * 1024 * 1024)
+
+ struct bcj {
+--- a/squashfs-tools/xz_wrapper.c
++++ b/squashfs-tools/xz_wrapper.c
+@@ -30,6 +30,7 @@
+ #include "squashfs_fs.h"
+ #include "xz_wrapper.h"
+ #include "compressor.h"
++#include "lzma_xz_options.h"
+
+ static struct bcj bcj[] = {
+ { "x86", LZMA_FILTER_X86, 0 },
+@@ -41,22 +42,18 @@ static struct bcj bcj[] = {
+ { NULL, LZMA_VLI_UNKNOWN, 0 }
+ };
+
+-static struct comp_opts comp_opts;
+-
+ static int filter_count = 1;
+-static int dictionary_size = 0;
+-static float dictionary_percent = 0;
+
+
+ static int xz_options(char *argv[], int argc)
+ {
+- int i;
+- char *name;
+-
+ if(strcmp(argv[0], "-Xbcj") == 0) {
++ int i;
++ char *name;
++
+ if(argc < 2) {
+ fprintf(stderr, "xz: -Xbcj missing filter\n");
+- goto failed;
++ return -2;
+ }
+
+ name = argv[1];
+@@ -76,190 +73,50 @@ static int xz_options(char *argv[], int
+ }
+ if(bcj[i].name == NULL) {
+ fprintf(stderr, "xz: -Xbcj unrecognised "
+- "filter\n");
+- goto failed;
+- }
+- }
+-
+- return 1;
+- } else if(strcmp(argv[0], "-Xdict-size") == 0) {
+- char *b;
+- float size;
+-
+- if(argc < 2) {
+- fprintf(stderr, "xz: -Xdict-size missing dict-size\n");
+- goto failed;
+- }
+-
+- size = strtof(argv[1], &b);
+- if(*b == '%') {
+- if(size <= 0 || size > 100) {
+- fprintf(stderr, "xz: -Xdict-size percentage "
+- "should be 0 < dict-size <= 100\n");
+- goto failed;
+- }
+-
+- dictionary_percent = size;
+- dictionary_size = 0;
+- } else {
+- if((float) ((int) size) != size) {
+- fprintf(stderr, "xz: -Xdict-size can't be "
+- "fractional unless a percentage of the"
+- " block size\n");
+- goto failed;
+- }
+-
+- dictionary_percent = 0;
+- dictionary_size = (int) size;
+-
+- if(*b == 'k' || *b == 'K')
+- dictionary_size *= 1024;
+- else if(*b == 'm' || *b == 'M')
+- dictionary_size *= 1024 * 1024;
+- else if(*b != '\0') {
+- fprintf(stderr, "xz: -Xdict-size invalid "
+- "dict-size\n");
+- goto failed;
++ "filter\n");
++ return -2;
+ }
+ }
+-
+ return 1;
++ } else {
++ return lzma_xz_options(argv, argc, LZMA_OPT_XZ);
+ }
+-
+- return -1;
+-
+-failed:
+- return -2;
+ }
+
+
+ static int xz_options_post(int block_size)
+ {
+- /*
+- * if -Xdict-size has been specified use this to compute the datablock
+- * dictionary size
+- */
+- if(dictionary_size || dictionary_percent) {
+- int n;
+-
+- if(dictionary_size) {
+- if(dictionary_size > block_size) {
+- fprintf(stderr, "xz: -Xdict-size is larger than"
+- " block_size\n");
+- goto failed;
+- }
+- } else
+- dictionary_size = block_size * dictionary_percent / 100;
+-
+- if(dictionary_size < 8192) {
+- fprintf(stderr, "xz: -Xdict-size should be 8192 bytes "
+- "or larger\n");
+- goto failed;
+- }
+-
+- /*
+- * dictionary_size must be storable in xz header as either
+- * 2^n or as 2^n+2^(n+1)
+- */
+- n = ffs(dictionary_size) - 1;
+- if(dictionary_size != (1 << n) &&
+- dictionary_size != ((1 << n) + (1 << (n + 1)))) {
+- fprintf(stderr, "xz: -Xdict-size is an unsupported "
+- "value, dict-size must be storable in xz "
+- "header\n");
+- fprintf(stderr, "as either 2^n or as 2^n+2^(n+1). "
+- "Example dict-sizes are 75%%, 50%%, 37.5%%, "
+- "25%%,\n");
+- fprintf(stderr, "or 32K, 16K, 8K etc.\n");
+- goto failed;
+- }
+-
+- } else
+- /* No -Xdict-size specified, use defaults */
+- dictionary_size = block_size;
+-
+- return 0;
+-
+-failed:
+- return -1;
++ return lzma_xz_options_post(block_size, LZMA_OPT_XZ);
+ }
+
+
+ static void *xz_dump_options(int block_size, int *size)
+ {
+- int flags = 0, i;
+-
+- /*
+- * don't store compressor specific options in file system if the
+- * default options are being used - no compressor options in the
+- * file system means the default options are always assumed
+- *
+- * Defaults are:
+- * metadata dictionary size: SQUASHFS_METADATA_SIZE
+- * datablock dictionary size: block_size
+- * 1 filter
+- */
+- if(dictionary_size == block_size && filter_count == 1)
+- return NULL;
++ int i, flags = 0;
+
+ for(i = 0; bcj[i].name; i++)
+ flags |= bcj[i].selected << i;
+
+- comp_opts.dictionary_size = dictionary_size;
+- comp_opts.flags = flags;
+-
+- SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
+-
+- *size = sizeof(comp_opts);
+- return &comp_opts;
++ return lzma_xz_dump_options(block_size, size, flags);
+ }
+
+
+ static int xz_extract_options(int block_size, void *buffer, int size)
+ {
+- struct comp_opts *comp_opts = buffer;
+- int flags, i, n;
+-
+- if(size == 0) {
+- /* set defaults */
+- dictionary_size = block_size;
+- flags = 0;
+- } else {
+- /* check passed comp opts struct is of the correct length */
+- if(size != sizeof(struct comp_opts))
+- goto failed;
+-
+- SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
+-
+- dictionary_size = comp_opts->dictionary_size;
+- flags = comp_opts->flags;
+-
+- /*
+- * check that the dictionary size seems correct - the dictionary
+- * size should 2^n or 2^n+2^(n+1)
+- */
+- n = ffs(dictionary_size) - 1;
+- if(dictionary_size != (1 << n) &&
+- dictionary_size != ((1 << n) + (1 << (n + 1))))
+- goto failed;
+- }
++ int ret = lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_XZ);
+
+- filter_count = 1;
+- for(i = 0; bcj[i].name; i++) {
+- if((flags >> i) & 1) {
+- bcj[i].selected = 1;
+- filter_count ++;
+- } else
+- bcj[i].selected = 0;
++ if (!ret) {
++ int i;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
++ for(i = 0; bcj[i].name; i++) {
++ if((opts->flags >> i) & 1) {
++ bcj[i].selected = 1;
++ filter_count ++;
++ } else
++ bcj[i].selected = 0;
++ }
+ }
+-
+- return 0;
+-
+-failed:
+- fprintf(stderr, "xz: error reading stored compressor options from "
+- "filesystem!\n");
+-
+- return -1;
++ return ret;
+ }
+
+
+@@ -268,6 +125,7 @@ static int xz_init(void **strm, int bloc
+ int i, j, filters = datablock ? filter_count : 1;
+ struct filter *filter = malloc(filters * sizeof(struct filter));
+ struct xz_stream *stream;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
+
+ if(filter == NULL)
+ goto failed;
+@@ -281,7 +139,7 @@ static int xz_init(void **strm, int bloc
+
+ memset(filter, 0, filters * sizeof(struct filter));
+
+- stream->dictionary_size = datablock ? dictionary_size :
++ stream->dictionary_size = datablock ? opts->dict_size :
+ SQUASHFS_METADATA_SIZE;
+
+ filter[0].filter[0].id = LZMA_FILTER_LZMA2;
+@@ -323,14 +181,25 @@ static int xz_compress(void *strm, void
+ lzma_ret res = 0;
+ struct xz_stream *stream = strm;
+ struct filter *selected = NULL;
++ struct lzma_xz_options *opts = lzma_xz_get_options();
+
+ stream->filter[0].buffer = dest;
+
+ for(i = 0; i < stream->filters; i++) {
++ uint32_t preset = opts->preset;
+ struct filter *filter = &stream->filter[i];
+
+- if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
+- goto failed;
++ if (opts->extreme)
++ preset |= LZMA_PRESET_EXTREME;
++
++ if(lzma_lzma_preset(&stream->opt, preset))
++ goto failed;
++
++ stream->opt.lc = opts->lc;
++ stream->opt.lp = opts->lp;
++ stream->opt.pb = opts->pb;
++ if (opts->fb)
++ stream->opt.nice_len = opts->fb;
+
+ stream->opt.dict_size = stream->dictionary_size;
+
+@@ -384,22 +253,13 @@ static int xz_uncompress(void *dest, voi
+
+ void xz_usage()
+ {
++ lzma_xz_usage(LZMA_OPT_XZ);
+ fprintf(stderr, "\t -Xbcj filter1,filter2,...,filterN\n");
+ fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
+ fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
+ fprintf(stderr, " the best compression.\n");
+ fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
+ fprintf(stderr, " powerpc, sparc, ia64\n");
+- fprintf(stderr, "\t -Xdict-size <dict-size>\n");
+- fprintf(stderr, "\t\tUse <dict-size> as the XZ dictionary size. The");
+- fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
+- fprintf(stderr, " percentage of the block size, or as an\n\t\t");
+- fprintf(stderr, "absolute value. The dictionary size must be less");
+- fprintf(stderr, " than or equal\n\t\tto the block size and 8192 bytes");
+- fprintf(stderr, " or larger. It must also be\n\t\tstorable in the xz");
+- fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
+- fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
+- fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
+ }
+
+
+--- a/squashfs-tools/Makefile
++++ b/squashfs-tools/Makefile
+@@ -140,6 +140,8 @@ COMPRESSORS += xz
+ endif
+
+ ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),)
++MKSQUASHFS_OBJS += lzma_xz_options.o
++UNSQUASHFS_OBJS += lzma_xz_options.o
+ ifneq ($(LZMA_LIB),)
+ MKSQUASHFS_OBJS += $(LZMA_LIB)
+ UNSQUASHFS_OBJS += $(LZMA_LIB)
diff --git a/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch b/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch
new file mode 100644
index 0000000..ad69b19
--- /dev/null
+++ b/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch
@@ -0,0 +1,72 @@
+--- a/squashfs-tools/squashfs_fs.h
++++ b/squashfs-tools/squashfs_fs.h
+@@ -30,6 +30,13 @@
+ #define SQUASHFS_MAGIC_SWAP 0x68737173
+ #define SQUASHFS_START 0
+
++/*
++ * Squashfs + LZMA
++ */
++
++#define SQUASHFS_MAGIC_LZMA 0x71736873
++#define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371
++
+ /* size of metadata (inode and directory) blocks */
+ #define SQUASHFS_METADATA_SIZE 8192
+ #define SQUASHFS_METADATA_LOG 13
+--- a/squashfs-tools/unsquashfs.c
++++ b/squashfs-tools/unsquashfs.c
+@@ -1463,10 +1463,12 @@ int read_super(char *source)
+ */
+ read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block),
+ &sBlk_4);
+- swap = sBlk_4.s_magic != SQUASHFS_MAGIC;
++ swap = (sBlk_4.s_magic != SQUASHFS_MAGIC &&
++ sBlk_4.s_magic != SQUASHFS_MAGIC_LZMA);
+ SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4);
+
+- if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 &&
++ if((sBlk_4.s_magic == SQUASHFS_MAGIC ||
++ sBlk_4.s_magic == SQUASHFS_MAGIC_LZMA) && sBlk_4.s_major == 4 &&
+ sBlk_4.s_minor == 0) {
+ s_ops.squashfs_opendir = squashfs_opendir_4;
+ s_ops.read_fragment = read_fragment_4;
+@@ -1479,7 +1481,11 @@ int read_super(char *source)
+ /*
+ * Check the compression type
+ */
+- comp = lookup_compressor_id(sBlk.s.compression);
++ if (sBlk_4.s_magic == SQUASHFS_MAGIC_LZMA)
++ comp = lookup_compressor("lzma");
++ else
++ comp = lookup_compressor_id(sBlk.s.compression);
++
+ return TRUE;
+ }
+
+@@ -1494,8 +1500,10 @@ int read_super(char *source)
+ * Check it is a SQUASHFS superblock
+ */
+ swap = 0;
+- if(sBlk_3.s_magic != SQUASHFS_MAGIC) {
+- if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) {
++ if(sBlk_3.s_magic != SQUASHFS_MAGIC &&
++ sBlk_3.s_magic != SQUASHFS_MAGIC_LZMA) {
++ if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP ||
++ sBlk_3.s_magic == SQUASHFS_MAGIC_LZMA_SWAP) {
+ squashfs_super_block_3 sblk;
+ ERROR("Reading a different endian SQUASHFS filesystem "
+ "on %s\n", source);
+@@ -1573,7 +1581,11 @@ int read_super(char *source)
+ /*
+ * 1.x, 2.x and 3.x filesystems use gzip compression.
+ */
+- comp = lookup_compressor("gzip");
++ if (sBlk.s.s_magic == SQUASHFS_MAGIC_LZMA)
++ comp = lookup_compressor("lzma");
++ else
++ comp = lookup_compressor("gzip");
++
+ return TRUE;
+
+ failed_mount:
diff --git a/tools/squashfs4/patches/180-openbsd_compat.patch b/tools/squashfs4/patches/180-openbsd_compat.patch
new file mode 100644
index 0000000..6d7a857
--- /dev/null
+++ b/tools/squashfs4/patches/180-openbsd_compat.patch
@@ -0,0 +1,26 @@
+diff -Nur squashfs4.2.orig/squashfs-tools/mksquashfs.c squashfs4.2/squashfs-tools/mksquashfs.c
+--- squashfs4.2.orig/squashfs-tools/mksquashfs.c Tue Mar 5 16:20:49 2013
++++ squashfs4.2/squashfs-tools/mksquashfs.c Tue Mar 5 16:25:10 2013
+@@ -32,6 +32,9 @@
+ #include <stdio.h>
+ #include <stddef.h>
+ #include <sys/time.h>
++#if defined(__OpenBSD__)
++#include <sys/param.h>
++#endif
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+diff -Nur squashfs4.2.orig/squashfs-tools/unsquashfs.h squashfs4.2/squashfs-tools/unsquashfs.h
+--- squashfs4.2.orig/squashfs-tools/unsquashfs.h Tue Mar 5 16:20:49 2013
++++ squashfs4.2/squashfs-tools/unsquashfs.h Tue Mar 5 16:25:57 2013
+@@ -25,6 +25,9 @@
+ #define TRUE 1
+ #define FALSE 0
+ #include <stdio.h>
++#if defined(__OpenBSD__)
++#include <sys/param.h>
++#endif
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <stdlib.h>
diff --git a/tools/squashfs4/patches/190-no_nonstatic_inline.patch b/tools/squashfs4/patches/190-no_nonstatic_inline.patch
new file mode 100644
index 0000000..7b5808a
--- /dev/null
+++ b/tools/squashfs4/patches/190-no_nonstatic_inline.patch
@@ -0,0 +1,36 @@
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -735,13 +735,13 @@ void cache_block_put(struct file_buffer
+ + (((char *)A) - data_cache)))
+
+
+-inline void inc_progress_bar()
++static inline void inc_progress_bar()
+ {
+ cur_uncompressed ++;
+ }
+
+
+-inline void update_progress_bar()
++static inline void update_progress_bar()
+ {
+ pthread_mutex_lock(&progress_mutex);
+ pthread_cond_signal(&progress_wait);
+@@ -749,7 +749,7 @@ inline void update_progress_bar()
+ }
+
+
+-inline void waitforthread(int i)
++static inline void waitforthread(int i)
+ {
+ TRACE("Waiting for thread %d\n", i);
+ while(thread[i] != 0)
+@@ -3358,7 +3358,7 @@ struct inode_info *lookup_inode(struct s
+ }
+
+
+-inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
++static inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
+ struct inode_info *inode_info, struct dir_info *dir)
+ {
+ if((dir->count % DIR_ENTRIES) == 0) {
diff --git a/tools/sstrip/Makefile b/tools/sstrip/Makefile
new file mode 100644
index 0000000..180bd17
--- /dev/null
+++ b/tools/sstrip/Makefile
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=sstrip
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(HOSTCC) $(HOST_CFLAGS) -include endian.h -o $(HOST_BUILD_DIR)/sstrip src/sstrip.c
+endef
+
+define Host/Install
+ $(CP) $(HOST_BUILD_DIR)/sstrip $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/sstrip
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/sstrip/src/sstrip.c b/tools/sstrip/src/sstrip.c
new file mode 100644
index 0000000..0508aaa
--- /dev/null
+++ b/tools/sstrip/src/sstrip.c
@@ -0,0 +1,465 @@
+/* http://www.muppetlabs.com/~breadbox/software/elfkickers.html */
+
+/* sstrip: Copyright (C) 1999-2001 by Brian Raiter, under the GNU
+ * General Public License. No warranty. See COPYING for details.
+ *
+ * Aug 23, 2004 Hacked by Manuel Novoa III <mjn3@codepoet.org> to
+ * handle targets of different endianness and/or elf class, making
+ * it more useful in a cross-devel environment.
+ */
+
+/* ============== original README ===================
+ *
+ * sstrip is a small utility that removes the contents at the end of an
+ * ELF file that are not part of the program's memory image.
+ *
+ * Most ELF executables are built with both a program header table and a
+ * section header table. However, only the former is required in order
+ * for the OS to load, link and execute a program. sstrip attempts to
+ * extract the ELF header, the program header table, and its contents,
+ * leaving everything else in the bit bucket. It can only remove parts of
+ * the file that occur at the end, after the parts to be saved. However,
+ * this almost always includes the section header table, and occasionally
+ * a few random sections that are not used when running a program.
+ *
+ * It should be noted that the GNU bfd library is (understandably)
+ * dependent on the section header table as an index to the file's
+ * contents. Thus, an executable file that has no section header table
+ * cannot be used with gdb, objdump, or any other program based upon the
+ * bfd library, at all. In fact, the program will not even recognize the
+ * file as a valid executable. (This limitation is noted in the source
+ * code comments for bfd, and is marked "FIXME", so this may change at
+ * some future date. However, I would imagine that it is a pretty
+ * low-priority item, as executables without a section header table are
+ * rare in the extreme.) This probably also explains why strip doesn't
+ * offer the option to do this.
+ *
+ * Shared library files may also have their section header table removed.
+ * Such a library will still function; however, it will no longer be
+ * possible for a compiler to link a new program against it.
+ *
+ * As an added bonus, sstrip also tries to removes trailing zero bytes
+ * from the end of the file. (This normally cannot be done with an
+ * executable that has a section header table.)
+ *
+ * sstrip is a very simplistic program. It depends upon the common
+ * practice of putting the parts of the file that contribute to the
+ * memory image at the front, and the remaining material at the end. This
+ * permits it to discard the latter material without affecting file
+ * offsets and memory addresses in what remains. Of course, the ELF
+ * standard permits files to be organized in almost any order, so if a
+ * pathological linker decided to put its section headers at the top,
+ * sstrip would be useless on such executables.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <elf.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/* The name of the program.
+ */
+static char const *progname;
+
+/* The name of the current file.
+ */
+static char const *filename;
+
+
+/* A simple error-handling function. FALSE is always returned for the
+ * convenience of the caller.
+ */
+static int err(char const *errmsg)
+{
+ fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg);
+ return FALSE;
+}
+
+/* A flag to signal the need for endian reversal.
+ */
+static int do_reverse_endian;
+
+/* Get a value from the elf header, compensating for endianness.
+ */
+#define EGET(X) \
+ (__extension__ ({ \
+ uint64_t __res; \
+ if (!do_reverse_endian) { \
+ __res = (X); \
+ } else if (sizeof(X) == 1) { \
+ __res = (X); \
+ } else if (sizeof(X) == 2) { \
+ __res = bswap_16((X)); \
+ } else if (sizeof(X) == 4) { \
+ __res = bswap_32((X)); \
+ } else if (sizeof(X) == 8) { \
+ __res = bswap_64((X)); \
+ } else { \
+ fprintf(stderr, "%s: %s: EGET failed for size %d\n", \
+ progname, filename, sizeof(X)); \
+ exit(EXIT_FAILURE); \
+ } \
+ __res; \
+ }))
+
+/* Set a value 'Y' in the elf header to 'X', compensating for endianness.
+ */
+#define ESET(Y,X) \
+ do if (!do_reverse_endian) { \
+ Y = (X); \
+ } else if (sizeof(Y) == 1) { \
+ Y = (X); \
+ } else if (sizeof(Y) == 2) { \
+ Y = bswap_16((uint16_t)(X)); \
+ } else if (sizeof(Y) == 4) { \
+ Y = bswap_32((uint32_t)(X)); \
+ } else if (sizeof(Y) == 8) { \
+ Y = bswap_64((uint64_t)(X)); \
+ } else { \
+ fprintf(stderr, "%s: %s: ESET failed for size %d\n", \
+ progname, filename, sizeof(Y)); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+
+/* A macro for I/O errors: The given error message is used only when
+ * errno is not set.
+ */
+#define ferr(msg) (err(errno ? strerror(errno) : (msg)))
+
+
+
+#define HEADER_FUNCTIONS(CLASS) \
+ \
+/* readelfheader() reads the ELF header into our global variable, and \
+ * checks to make sure that this is in fact a file that we should be \
+ * munging. \
+ */ \
+static int readelfheader ## CLASS (int fd, Elf ## CLASS ## _Ehdr *ehdr) \
+{ \
+ if (read(fd, ((char *)ehdr)+EI_NIDENT, sizeof(*ehdr) - EI_NIDENT) \
+ != sizeof(*ehdr) - EI_NIDENT) \
+ return ferr("missing or incomplete ELF header."); \
+ \
+ /* Verify the sizes of the ELF header and the program segment \
+ * header table entries. \
+ */ \
+ if (EGET(ehdr->e_ehsize) != sizeof(Elf ## CLASS ## _Ehdr)) \
+ return err("unrecognized ELF header size."); \
+ if (EGET(ehdr->e_phentsize) != sizeof(Elf ## CLASS ## _Phdr)) \
+ return err("unrecognized program segment header size."); \
+ \
+ /* Finally, check the file type. \
+ */ \
+ if (EGET(ehdr->e_type) != ET_EXEC && EGET(ehdr->e_type) != ET_DYN) \
+ return err("not an executable or shared-object library."); \
+ \
+ return TRUE; \
+} \
+ \
+/* readphdrtable() loads the program segment header table into memory. \
+ */ \
+static int readphdrtable ## CLASS (int fd, Elf ## CLASS ## _Ehdr const *ehdr, \
+ Elf ## CLASS ## _Phdr **phdrs) \
+{ \
+ size_t size; \
+ \
+ if (!EGET(ehdr->e_phoff) || !EGET(ehdr->e_phnum) \
+) return err("ELF file has no program header table."); \
+ \
+ size = EGET(ehdr->e_phnum) * sizeof **phdrs; \
+ if (!(*phdrs = malloc(size))) \
+ return err("Out of memory!"); \
+ \
+ errno = 0; \
+ if (read(fd, *phdrs, size) != (ssize_t)size) \
+ return ferr("missing or incomplete program segment header table."); \
+ \
+ return TRUE; \
+} \
+ \
+/* getmemorysize() determines the offset of the last byte of the file \
+ * that is referenced by an entry in the program segment header table. \
+ * (Anything in the file after that point is not used when the program \
+ * is executing, and thus can be safely discarded.) \
+ */ \
+static int getmemorysize ## CLASS (Elf ## CLASS ## _Ehdr const *ehdr, \
+ Elf ## CLASS ## _Phdr const *phdrs, \
+ unsigned long *newsize) \
+{ \
+ Elf ## CLASS ## _Phdr const *phdr; \
+ unsigned long size, n; \
+ int i; \
+ \
+ /* Start by setting the size to include the ELF header and the \
+ * complete program segment header table. \
+ */ \
+ size = EGET(ehdr->e_phoff) + EGET(ehdr->e_phnum) * sizeof *phdrs; \
+ if (size < sizeof *ehdr) \
+ size = sizeof *ehdr; \
+ \
+ /* Then keep extending the size to include whatever data the \
+ * program segment header table references. \
+ */ \
+ for (i = 0, phdr = phdrs ; i < EGET(ehdr->e_phnum) ; ++i, ++phdr) { \
+ if (EGET(phdr->p_type) != PT_NULL) { \
+ n = EGET(phdr->p_offset) + EGET(phdr->p_filesz); \
+ if (n > size) \
+ size = n; \
+ } \
+ } \
+ \
+ *newsize = size; \
+ return TRUE; \
+} \
+ \
+/* modifyheaders() removes references to the section header table if \
+ * it was stripped, and reduces program header table entries that \
+ * included truncated bytes at the end of the file. \
+ */ \
+static int modifyheaders ## CLASS (Elf ## CLASS ## _Ehdr *ehdr, \
+ Elf ## CLASS ## _Phdr *phdrs, \
+ unsigned long newsize) \
+{ \
+ Elf ## CLASS ## _Phdr *phdr; \
+ int i; \
+ \
+ /* If the section header table is gone, then remove all references \
+ * to it in the ELF header. \
+ */ \
+ if (EGET(ehdr->e_shoff) >= newsize) { \
+ ESET(ehdr->e_shoff,0); \
+ ESET(ehdr->e_shnum,0); \
+ ESET(ehdr->e_shentsize,0); \
+ ESET(ehdr->e_shstrndx,0); \
+ } \
+ \
+ /* The program adjusts the file size of any segment that was \
+ * truncated. The case of a segment being completely stripped out \
+ * is handled separately. \
+ */ \
+ for (i = 0, phdr = phdrs ; i < EGET(ehdr->e_phnum) ; ++i, ++phdr) { \
+ if (EGET(phdr->p_offset) >= newsize) { \
+ ESET(phdr->p_offset,newsize); \
+ ESET(phdr->p_filesz,0); \
+ } else if (EGET(phdr->p_offset) + EGET(phdr->p_filesz) > newsize) { \
+ ESET(phdr->p_filesz, newsize - EGET(phdr->p_offset)); \
+ } \
+ } \
+ \
+ return TRUE; \
+} \
+ \
+/* commitchanges() writes the new headers back to the original file \
+ * and sets the file to its new size. \
+ */ \
+static int commitchanges ## CLASS (int fd, Elf ## CLASS ## _Ehdr const *ehdr, \
+ Elf ## CLASS ## _Phdr *phdrs, \
+ unsigned long newsize) \
+{ \
+ size_t n; \
+ \
+ /* Save the changes to the ELF header, if any. \
+ */ \
+ if (lseek(fd, 0, SEEK_SET)) \
+ return ferr("could not rewind file"); \
+ errno = 0; \
+ if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) \
+ return err("could not modify file"); \
+ \
+ /* Save the changes to the program segment header table, if any. \
+ */ \
+ if (lseek(fd, EGET(ehdr->e_phoff), SEEK_SET) == (off_t)-1) { \
+ err("could not seek in file."); \
+ goto warning; \
+ } \
+ n = EGET(ehdr->e_phnum) * sizeof *phdrs; \
+ if (write(fd, phdrs, n) != (ssize_t)n) { \
+ err("could not write to file"); \
+ goto warning; \
+ } \
+ \
+ /* Eleventh-hour sanity check: don't truncate before the end of \
+ * the program segment header table. \
+ */ \
+ if (newsize < EGET(ehdr->e_phoff) + n) \
+ newsize = EGET(ehdr->e_phoff) + n; \
+ \
+ /* Chop off the end of the file. \
+ */ \
+ if (ftruncate(fd, newsize)) { \
+ err("could not resize file"); \
+ goto warning; \
+ } \
+ \
+ return TRUE; \
+ \
+ warning: \
+ return err("ELF file may have been corrupted!"); \
+}
+
+
+/* First elements of Elf32_Ehdr and Elf64_Ehdr are common.
+ */
+static int readelfheaderident(int fd, Elf32_Ehdr *ehdr)
+{
+ errno = 0;
+ if (read(fd, ehdr, EI_NIDENT) != EI_NIDENT)
+ return ferr("missing or incomplete ELF header.");
+
+ /* Check the ELF signature.
+ */
+ if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
+ ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
+ ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
+ ehdr->e_ident[EI_MAG3] == ELFMAG3))
+ {
+ err("missing ELF signature.");
+ return -1;
+ }
+
+ /* Compare the file's class and endianness with the program's.
+ */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
+ do_reverse_endian = 0;
+ } else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
+/* fprintf(stderr, "ELF file has different endianness.\n"); */
+ do_reverse_endian = 1;
+ }
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
+/* fprintf(stderr, "ELF file has different endianness.\n"); */
+ do_reverse_endian = 1;
+ } else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
+ do_reverse_endian = 0;
+ }
+#else
+#error unkown endianness
+#endif
+ else {
+ err("Unsupported endianness");
+ return -1;
+ }
+
+ /* Check the target architecture.
+ */
+/* if (EGET(ehdr->e_machine) != ELF_ARCH) { */
+/* /\* return err("ELF file created for different architecture."); *\/ */
+/* fprintf(stderr, "ELF file created for different architecture.\n"); */
+/* } */
+ return ehdr->e_ident[EI_CLASS];
+}
+
+
+HEADER_FUNCTIONS(32)
+
+HEADER_FUNCTIONS(64)
+
+/* truncatezeros() examines the bytes at the end of the file's
+ * size-to-be, and reduces the size to exclude any trailing zero
+ * bytes.
+ */
+static int truncatezeros(int fd, unsigned long *newsize)
+{
+ unsigned char contents[1024];
+ unsigned long size, n;
+
+ size = *newsize;
+ do {
+ n = sizeof contents;
+ if (n > size)
+ n = size;
+ if (lseek(fd, size - n, SEEK_SET) == (off_t)-1)
+ return ferr("cannot seek in file.");
+ if (read(fd, contents, n) != (ssize_t)n)
+ return ferr("cannot read file contents");
+ while (n && !contents[--n])
+ --size;
+ } while (size && !n);
+
+ /* Sanity check.
+ */
+ if (!size)
+ return err("ELF file is completely blank!");
+
+ *newsize = size;
+ return TRUE;
+}
+
+/* main() loops over the cmdline arguments, leaving all the real work
+ * to the other functions.
+ */
+int main(int argc, char *argv[])
+{
+ int fd;
+ union {
+ Elf32_Ehdr ehdr32;
+ Elf64_Ehdr ehdr64;
+ } e;
+ union {
+ Elf32_Phdr *phdrs32;
+ Elf64_Phdr *phdrs64;
+ } p;
+ unsigned long newsize;
+ char **arg;
+ int failures = 0;
+
+ if (argc < 2 || argv[1][0] == '-') {
+ printf("Usage: sstrip FILE...\n"
+ "sstrip discards all nonessential bytes from an executable.\n\n"
+ "Version 2.0-X Copyright (C) 2000,2001 Brian Raiter.\n"
+ "Cross-devel hacks Copyright (C) 2004 Manuel Novoa III.\n"
+ "This program is free software, licensed under the GNU\n"
+ "General Public License. There is absolutely no warranty.\n");
+ return EXIT_SUCCESS;
+ }
+
+ progname = argv[0];
+
+ for (arg = argv + 1 ; *arg != NULL ; ++arg) {
+ filename = *arg;
+
+ fd = open(*arg, O_RDWR);
+ if (fd < 0) {
+ ferr("can't open");
+ ++failures;
+ continue;
+ }
+
+ switch (readelfheaderident(fd, &e.ehdr32)) {
+ case ELFCLASS32:
+ if (!(readelfheader32(fd, &e.ehdr32) &&
+ readphdrtable32(fd, &e.ehdr32, &p.phdrs32) &&
+ getmemorysize32(&e.ehdr32, p.phdrs32, &newsize) &&
+ truncatezeros(fd, &newsize) &&
+ modifyheaders32(&e.ehdr32, p.phdrs32, newsize) &&
+ commitchanges32(fd, &e.ehdr32, p.phdrs32, newsize)))
+ ++failures;
+ break;
+ case ELFCLASS64:
+ if (!(readelfheader64(fd, &e.ehdr64) &&
+ readphdrtable64(fd, &e.ehdr64, &p.phdrs64) &&
+ getmemorysize64(&e.ehdr64, p.phdrs64, &newsize) &&
+ truncatezeros(fd, &newsize) &&
+ modifyheaders64(&e.ehdr64, p.phdrs64, newsize) &&
+ commitchanges64(fd, &e.ehdr64, p.phdrs64, newsize)))
+ ++failures;
+ break;
+ default:
+ ++failures;
+ break;
+ }
+ close(fd);
+ }
+
+ return failures ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/tools/tar/Makefile b/tools/tar/Makefile
new file mode 100644
index 0000000..975e783
--- /dev/null
+++ b/tools/tar/Makefile
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tar
+PKG_VERSION:=1.28
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/tar
+PKG_MD5SUM:=49b6306167724fe48f419a33a5beb857
+
+HOST_BUILD_PARALLEL := 1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOSTCC := $(HOSTCC_NOCACHE)
+HOSTCXX := $(HOSTCXX_NOCACHE)
+
+HOST_CONFIGURE_ARGS += \
+ --without-posix-acls \
+ --without-selinux \
+ --without-xattrs \
+ --disable-acl \
+ --disable-nls
+
+$(eval $(call HostBuild))
diff --git a/tools/tar/patches/100-fix_xattr_disable.patch b/tools/tar/patches/100-fix_xattr_disable.patch
new file mode 100644
index 0000000..5735bd2
--- /dev/null
+++ b/tools/tar/patches/100-fix_xattr_disable.patch
@@ -0,0 +1,17 @@
+--- a/lib/xattr-at.c
++++ b/lib/xattr-at.c
+@@ -18,6 +18,8 @@
+
+ #include <config.h>
+
++#ifdef HAVE_XATTRS
++
+ #include "xattr-at.h"
+ #include "openat.h"
+
+@@ -108,3 +110,5 @@
+ #undef AT_FUNC_RESULT
+ #undef AT_FUNC_POST_FILE_PARAM_DECLS
+ #undef AT_FUNC_POST_FILE_ARGS
++
++#endif
diff --git a/tools/upslug2/Makefile b/tools/upslug2/Makefile
new file mode 100644
index 0000000..33b1ff5
--- /dev/null
+++ b/tools/upslug2/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2009-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=upslug2
+PKG_VERSION:=20071227
+
+PKG_SOURCE_URL:=http://svn.nslu2-linux.org/svnroot/upslug2/trunk
+PKG_SOURCE_PROTO:=svn
+PKG_SOURCE_SUBDIR:=upslug2-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=41
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+
+include $(INCLUDE_DIR)/host-build.mk
+
+unexport CFLAGS
+
+define Host/Configure
+ (cd $(HOST_BUILD_DIR); \
+ aclocal && autoconf && \
+ autoheader && \
+ automake --add-missing; \
+ )
+ $(Host/Configure/Default)
+endef
+
+ifneq ($(HOST_OS),Linux)
+ HOST_CONFIGURE_ARGS += --with-libpcap
+endif
+
+$(eval $(call HostBuild))
diff --git a/tools/upslug2/patches/100-libpcap_fix.patch b/tools/upslug2/patches/100-libpcap_fix.patch
new file mode 100644
index 0000000..1e14de4
--- /dev/null
+++ b/tools/upslug2/patches/100-libpcap_fix.patch
@@ -0,0 +1,153 @@
+--- a/pcap_wire.cc
++++ b/pcap_wire.cc
+@@ -18,6 +18,7 @@
+
+ #include <sys/time.h>
+ #include <sys/select.h>
++#include <sys/poll.h>
+
+ /* Ways of finding the hardware MAC on this machine... */
+ /* This is the Linux only fallback. */
+@@ -130,20 +131,18 @@ namespace NSLU2Upgrade {
+ * non-static (real) Handler.
+ */
+ void Handler(const struct pcap_pkthdr *packet_header, const u_char *packet) {
+- /* This should only be called once... */
+- if (captured)
+- throw std::logic_error("Handler called twice");
+-
+ /* Verify the protocol and originating address of the packet, then
+ * return this packet.
+ */
++ if (captured)
++ return;
+ if (packet_header->caplen > 14 && (broadcast ||
+ std::memcmp(packet+6, header, 6) == 0)) {
+- /* Record the address and copy the data */
+- std::memcpy(source, packet+6, 6);
+ const size_t len(packet_header->caplen - 14);
+ if (len > captureSize)
+- throw std::logic_error("packet too long");
++ return;
++ /* Record the address and copy the data */
++ std::memcpy(source, packet+6, 6);
+ std::memcpy(captureBuffer, packet+14, len);
+ captureSize = len;
+ captured = true;
+@@ -156,7 +155,7 @@ namespace NSLU2Upgrade {
+ * packet and the buffer should be big enough.
+ */
+ if (packet_header->caplen < packet_header->len)
+- throw std::logic_error("truncated packet");
++ return;
+
+ /*IGNORE EVIL: known evil cast */
+ reinterpret_cast<PCapWire*>(user)->Handler(packet_header, packet);
+@@ -173,56 +172,24 @@ namespace NSLU2Upgrade {
+ virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
+ /* Now try to read packets until the timeout has been consumed.
+ */
+- struct timeval tvStart;
+- if (timeout > 0 && gettimeofday(&tvStart, 0) != 0)
+- throw OSError(errno, "gettimeofday(base)");
++ int time_count;
+
+ captureBuffer = buffer;
+ captureSize = size;
+ captured = false;
++ time_count = timeout / 2000; /* 2 ms intervals */
++ time_count++;
+ do {
+ /*IGNORE EVIL: known evil cast */
+- int count(pcap_dispatch(pcap, 1, PCapHandler,
+- reinterpret_cast<u_char*>(this)));
++ int count = pcap_dispatch(pcap, 1, PCapHandler,
++ reinterpret_cast<u_char*>(this));
+
+- if (count > 0) {
+- /* Were any packets handled? */
+- if (captured) {
+- size = captureSize;
+- return;
+- }
+- /* else try again. */
+- } else if (count == 0) {
+- /* Nothing to handle - do the timeout, do this
+- * by waiting a bit then trying again, the trick
+- * to this is to work out how long to wait each
+- * time, for the moment a 10ms delay is used.
+- */
+- if (timeout == 0)
+- break;
+-
+- struct timeval tvNow;
+- if (gettimeofday(&tvNow, 0) != 0)
+- throw OSError(errno, "gettimeofday(now)");
+-
+- unsigned long t(tvNow.tv_sec - tvStart.tv_sec);
+- t *= 1000000;
+- t += tvNow.tv_usec;
+- t -= tvStart.tv_usec;
+- if (t > timeout)
+- break;
+-
+- tvNow.tv_sec = 0;
+- tvNow.tv_usec = timeout-t;
+- if (tvNow.tv_usec > 10000)
+- tvNow.tv_usec = 10000;
+-
+- /* Delay, may be interrupted - this should
+- * be portable to the BSDs (since the
+- * technique originates in BSD.)
+- */
+- (void)select(0, 0, 0, 0, &tvNow);
+- } else {
++ /* Were any packets handled? */
++ if (captured) {
++ size = captureSize;
++ return;
++ }
++ if (count < 0) {
+ /* Error condition. */
+ if (count == -1) {
+ if (errno != EINTR)
+@@ -232,7 +199,8 @@ namespace NSLU2Upgrade {
+ } else
+ throw std::logic_error("pcap unexpected result");
+ }
+- } while (timeout != 0);
++ time_count--;
++ } while (time_count > 0);
+
+ /* Here on timeout. */
+ size = 0;
+@@ -288,6 +256,7 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
+ const unsigned char *mac, const unsigned char *address, int uid) {
+ /* This is used to store the error passed to throw. */
+ static char PCapErrbuf[PCAP_ERRBUF_SIZE];
++ struct bpf_program fp;
+
+ /* Check the device name. If not given use 'DEFAULT_ETHERNET_IF'. */
+ if (device == NULL)
+@@ -301,20 +270,12 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
+ * for other ethernet MACs. (Because the code above does not
+ * check that the destination matches the device in use).
+ */
+- pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf);
++ pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf);
+
+ if (pcap == NULL)
+ throw WireError(errno, PCapErrbuf);
+ }
+
+- /* Always do a non-blocking read, because the 'timeout' above
+- * doesn't work on Linux (return is immediate) and on OSX (and
+- * maybe other BSDs) the interface tends to hang waiting for
+- * the timeout to expire even after receiving a single packet.
+- */
+- if (pcap_setnonblock(pcap, true, PCapErrbuf))
+- throw WireError(errno, PCapErrbuf);
+-
+ try {
+ /* The MAC of the transmitting device is needed - without
+ * this the return packet won't go to the right place!
diff --git a/tools/upslug2/patches/110-wrt350nv2_support.patch b/tools/upslug2/patches/110-wrt350nv2_support.patch
new file mode 100644
index 0000000..eea7cc4
--- /dev/null
+++ b/tools/upslug2/patches/110-wrt350nv2_support.patch
@@ -0,0 +1,279 @@
+--- a/nslu2_image.cc
++++ b/nslu2_image.cc
+@@ -54,28 +54,44 @@ namespace NSLU2Image {
+ int &address, int &length) {
+ address = image.tellg();
+ length = buffer_length;
+- if (address+length > NSLU2Protocol::FlashSize)
+- length = NSLU2Protocol::FlashSize-address;
++ if (address+length > EndAddress)
++ length = EndAddress-address;
+ if (length > 0)
+ SafeRead(&image, buffer, length, "image (read)");
+ }
+
++ virtual void GetBoundaries(int &start, int &end)
++ {
++ start = BaseAddress;
++ end = EndAddress;
++ }
++
+ /* Rewind to the start of the image (or the Kernel if not
+ * doing a complete reprogram).
+ */
+ virtual void Rewind(void) {
+- SafeSeek(&image, reprogram ? 0 : NSLU2Protocol::BaseAddress,
++ SafeSeek(&image, reprogram ? 0 : BaseAddress,
+ "image (seek)");
+ }
+
+ private:
++ int BaseAddress;
++ int EndAddress;
++
+ /* Validate that this really is an image file. */
+ void Validate(const char *i) {
+ char signature[8];
+
+ SafeSeek(&image, -8, i, std::ios::end);
+ SafeRead(&image, signature, 8, i);
+- if (memcmp(signature, "eRcOmM", 6) != 0)
++
++ if (memcmp(signature, "eRcOmM", 6) == 0) {
++ BaseAddress = NSLU2Protocol::BaseAddress;
++ EndAddress = NSLU2Protocol::FlashSize;
++ } else if (memcmp(signature + 1, "sErCoMm", 7) == 0) {
++ BaseAddress = 0;
++ EndAddress = NSLU2Protocol::FlashSize - 0x40000;
++ } else
+ throw NSLU2Image::FileError(DataError, i, 0);
+ }
+
+@@ -93,6 +109,12 @@ namespace NSLU2Image {
+ virtual ~SynthesiseImage() {
+ }
+
++ void GetBoundaries(int &start, int &end)
++ {
++ start = NSLU2Protocol::BaseAddress;
++ end = NSLU2Protocol::FlashSize;
++ }
++
+ /* Get the next block of bytes, returns an address and length, false if
+ * there is a problem.
+ */
+--- a/nslu2_image.h
++++ b/nslu2_image.h
+@@ -35,6 +35,8 @@ namespace NSLU2Image {
+ virtual ~Image() {
+ }
+
++ virtual void GetBoundaries(int &start, int &end) = 0;
++
+ /* Get the next block of bytes, returns an address and length.
+ */
+ virtual void GetBytes(char *buffer, size_t buffer_length,
+--- a/nslu2_upgrade.cc
++++ b/nslu2_upgrade.cc
+@@ -95,7 +95,7 @@ namespace NSLU2Upgrade {
+
+ class RealDoUpgrade : public DoUpgrade {
+ public:
+- RealDoUpgrade(Wire *w, Progress *p, bool r) :
++ RealDoUpgrade(Wire *w, Progress *p, bool r, int start, int end) :
+ wire(w), progress(p), sequenceError(-1), reprogram(r),
+ lastType(NSLU2Protocol::InvalidType) {
+ if (reprogram) {
+@@ -105,6 +105,8 @@ namespace NSLU2Upgrade {
+ NSLU2Protocol::UpgradeStartPacket packet(seq);
+ wire->Send(packet.PacketBuffer(), packet.PacketLength());
+ }
++ BaseAddress = start;
++ EndAddress = end;
+ }
+
+ virtual ~RealDoUpgrade() {
+@@ -205,8 +207,8 @@ namespace NSLU2Upgrade {
+
+ };
+
+- DoUpgrade *DoUpgrade::MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram) {
+- return new RealDoUpgrade(wire, progress, reprogram);
++ DoUpgrade *DoUpgrade::MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram, int start, int end) {
++ return new RealDoUpgrade(wire, progress, reprogram, start, end);
+ }
+ };
+
+@@ -421,13 +423,18 @@ void NSLU2Upgrade::RealDoUpgrade::Upgrad
+ /* Simple upgrade programs only the addresses beyound BaseAddress,
+ * reprogram overwrites the whole flash.
+ */
+- if (!reprogram && address < NSLU2Protocol::BaseAddress) {
++ if (!reprogram && address < BaseAddress) {
+ length += address;
+- if (length <= NSLU2Protocol::BaseAddress)
++ if (length <= BaseAddress)
+ return; /* nothing to do. */
+- address = NSLU2Protocol::BaseAddress;
++ address = BaseAddress;
+ length -= address;
+ }
++ if (!reprogram && address + length > EndAddress) {
++ if (address >= EndAddress)
++ return; /* nothing to do. */
++ length -= EndAddress - address;
++ }
+
+ #if 1
+ /* Skip blocks of 255 valued bytes - the erase clears the flash to this
+@@ -495,11 +502,11 @@ void NSLU2Upgrade::RealDoUpgrade::Verify
+ Finish();
+
+ /* Verify never verifies anything below BaseAddress. */
+- if (address < NSLU2Protocol::BaseAddress) {
++ if (address < BaseAddress) {
+ length += address;
+- if (length <= NSLU2Protocol::BaseAddress)
++ if (length <= BaseAddress)
+ return; /* nothing to do. */
+- address = NSLU2Protocol::BaseAddress;
++ address = BaseAddress;
+ length -= address;
+ }
+
+--- a/nslu2_upgrade.h
++++ b/nslu2_upgrade.h
+@@ -206,6 +206,8 @@ namespace NSLU2Upgrade {
+
+ class DoUpgrade {
+ public:
++ int BaseAddress;
++ int EndAddress;
+ virtual ~DoUpgrade() {
+ }
+
+@@ -228,7 +230,7 @@ namespace NSLU2Upgrade {
+ virtual void Reboot(void) = 0;
+ /* Reboot the NSLU2. */
+
+- static DoUpgrade *MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram);
++ static DoUpgrade *MakeDoUpgrade(Wire *wire, Progress *progress, bool reprogram, int start, int end);
+ /* Instantiate a real DoUpgrade, returns NULL if the object
+ * cannot be instantiated.
+ *
+--- a/upslug2.cc
++++ b/upslug2.cc
+@@ -21,8 +21,8 @@
+
+ class ProgressBar : public UpSlug2::CharacterProgressBar<80> {
+ public:
+- ProgressBar(bool reprogram, const unsigned char *t) :
+- UpSlug2::CharacterProgressBar<80>(reprogram, 64),
++ ProgressBar(bool reprogram, const unsigned char *t, int start, int end) :
++ UpSlug2::CharacterProgressBar<80>(reprogram, 64, start, end),
+ target(t), displayed(false), ticker(0) {
+ }
+
+@@ -95,7 +95,7 @@ private:
+ else if (seen == -1) {
+ seen = 0;
+ if (!reprogram)
+- sent -= NSLU2Protocol::BaseAddress;
++ sent -= NSLU2Protocol::FlashSize - (EndAddress - BaseAddress);
+ } else
+ sent -= seen;
+
+@@ -423,7 +423,7 @@ int main(int argc, char **argv) {
+ { 0, 0, 0, 0 }
+ };
+
+- do switch (getopt_long(argc, argv, "he:d:t:f:vUni:Ck:r:R:j:p:P:T:F:E:", options, 0)) {
++ do switch (getopt_long(argc, argv, "he:d:t:f:vUni:Ck:r:R:j:op:P:T:F:E:", options, 0)) {
+ case -1: if (optind < argc) {
+ std::fprintf(stderr, "%s: unrecognised option\n", argv[optind]);
+ std::exit(1);
+@@ -523,16 +523,22 @@ done:
+
+ if (mac && got_kernel) {
+ Pointer<NSLU2Upgrade::Wire> wire(NSLU2Upgrade::Wire::MakeWire(device, fromMac, mac, euid));
+- ProgressBar progress(reprogram, mac);
++ int BaseAddress = NSLU2Protocol::BaseAddress;
++ int EndAddress = NSLU2Protocol::FlashSize;
+
+ if (full_image) { /* complete image. */
+ /* The full image case allows a complete reprogram. */
++ NSLU2Image::Image *image_p;
+ Pointer<NSLU2Image::Image> image(
+ NSLU2Image::Image::MakeImage(
+ reprogram, full_image));
++ image_p = image.p;
++ image_p->GetBoundaries(BaseAddress, EndAddress);
++ ProgressBar progress(reprogram, mac, BaseAddress, EndAddress);
+ Pointer<NSLU2Upgrade::DoUpgrade> upgrade(
+ NSLU2Upgrade::DoUpgrade::MakeDoUpgrade(
+- wire.p, &progress, reprogram));
++ wire.p, &progress, reprogram,
++ BaseAddress, EndAddress));
+ progress.FirstDisplay();
+ Upgrade(upgrade.p, image.p, no_upgrade, no_verify);
+ progress.EndDisplay();
+@@ -551,9 +557,11 @@ done:
+ fis_payload,
+ product_id, protocol_id,
+ firmware_version, extra_version));
++ ProgressBar progress(reprogram, mac, BaseAddress, EndAddress);
+ Pointer<NSLU2Upgrade::DoUpgrade> upgrade(
+ NSLU2Upgrade::DoUpgrade::MakeDoUpgrade(
+- wire.p, &progress, false));
++ wire.p, &progress, false,
++ BaseAddress, EndAddress));
+ progress.FirstDisplay();
+ Upgrade(upgrade.p, image.p, no_upgrade, no_verify);
+ progress.EndDisplay();
+--- a/upslug2_progress.h
++++ b/upslug2_progress.h
+@@ -161,15 +161,19 @@ namespace UpSlug2 {
+ Timedout, /* *: timeout on a sent packet for this address. */
+ NumberOfStates
+ } Status;
+-
++ int BaseAddress;
++ int EndAddress;
++
+ /* reprogram says whether this is a full reprogram (the entire
+ * flash will be erased) or not (the leading, RedBoot, SysConf
+ * partitions are not erased).
+ * resolution should be about 6 for a command line (character)
+ * progress bar and 8 for a GUI (pixel) progress bar.
+ */
+- ProgressBar(bool r) :
++ ProgressBar(bool r, int start, int end) :
+ reprogram(r), timeout(false), retransmit(false), status(Init) {
++ BaseAddress = start;
++ EndAddress = end;
+ }
+
+ /* lowWaterMark..(highWaterMark-1) bytes are in state 'st',
+@@ -179,8 +183,8 @@ namespace UpSlug2 {
+ /* These initial settings cover the majority of cases
+ * correctly.
+ */
+- lowWaterMark = reprogram ? 0 : NSLU2Protocol::BaseAddress;
+- highWaterMark = status >= st ? NSLU2Protocol::FlashSize-1 : 0;
++ lowWaterMark = reprogram ? 0 : BaseAddress;
++ highWaterMark = status >= st ? EndAddress-1 : 0;
+ switch (st) {
+ case Init:
+ /* Everything has an initial value... */
+@@ -286,9 +290,9 @@ namespace UpSlug2 {
+ */
+ template <int characters> class CharacterProgressBar : public ProgressBar {
+ public:
+- CharacterProgressBar(bool reprogram, int n, const char ind[NumberOfStates] = 0) :
++ CharacterProgressBar(bool reprogram, int n, int start, int end, const char ind[NumberOfStates] = 0) :
+ numberOfCharacters(n > characters || n < 1 ? characters : n),
+- ProgressBar(reprogram) {
++ ProgressBar(reprogram, start, end) {
+ if (ind)
+ std::memcpy(indicators, ind, NumberOfStates);
+ else
diff --git a/tools/upx/Makefile b/tools/upx/Makefile
new file mode 100644
index 0000000..7f212af
--- /dev/null
+++ b/tools/upx/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2011-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=upx
+PKG_VERSION:=3.09
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-src.tar.bz2
+PKG_SOURCE_URL:=@SF/upx
+PKG_MD5SUM:=1253da46eac54a217eb73e2d44818e53
+PKG_CAT:=bzcat
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)-$(PKG_VERSION)-src
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ rm -f $(HOST_BUILD_DIR)/src/.depend
+ $(MAKE) UPX_LZMADIR="$(BUILD_DIR_HOST)/lzma-4.65" -C $(HOST_BUILD_DIR)/src \
+ CXXFLAGS_WERROR="" LDFLAGS="$(HOST_LDFLAGS)" \
+ CXX="$(HOSTCXX)"
+endef
+
+define Host/Install
+ $(CP) $(HOST_BUILD_DIR)/src/upx.out $(STAGING_DIR_HOST)/bin/upx
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/upx
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/upx/patches/100-lzmaonly.patch b/tools/upx/patches/100-lzmaonly.patch
new file mode 100644
index 0000000..f8e8d0b
--- /dev/null
+++ b/tools/upx/patches/100-lzmaonly.patch
@@ -0,0 +1,156 @@
+--- a/src/compress.cpp
++++ b/src/compress.cpp
+@@ -41,7 +41,7 @@ unsigned upx_adler32(const void *buf, un
+ if (len == 0)
+ return adler;
+ assert(buf != NULL);
+-#if 0
++#if !(WITH_UCL)
+ return adler32(adler, (const Bytef *) buf, len); // zlib
+ #elif (WITH_UCL)
+ return ucl_adler32(adler, (const ucl_bytep) buf, len);
+--- a/src/conf.h
++++ b/src/conf.h
+@@ -179,7 +179,7 @@
+ # undef __unix
+ #endif
+
+-#if !defined(WITH_UCL)
++#if defined(WITH_UCL)
+ # define WITH_UCL 1
+ #endif
+ #if 0 && !defined(WITH_LZMA)
+@@ -640,7 +640,11 @@ struct lzma_compress_config_t
+ };
+
+
++#if (WITH_UCL)
+ struct ucl_compress_config_t : public REAL_ucl_compress_config_t
++#else
++struct ucl_compress_config_t
++#endif
+ {
+ void reset() { memset(this, 0xff, sizeof(*this)); }
+ };
+@@ -692,7 +696,9 @@ struct lzma_compress_result_t
+
+ struct ucl_compress_result_t
+ {
++#if (WITH_UCL)
+ ucl_uint result[16];
++#endif
+
+ void reset() { memset(this, 0, sizeof(*this)); }
+ };
+--- a/src/main.cpp
++++ b/src/main.cpp
+@@ -618,7 +618,9 @@ static int do_option(int optc, const cha
+ opt->method = -1;
+ opt->all_filters = true;
+ opt->filter = -1;
++#if (WITH_UCL)
+ opt->crp.crp_ucl.m_size = 999999;
++#endif
+ /* fallthrough */
+ case 900: // --best
+ if (!set_method(-1, 10))
+@@ -709,6 +711,7 @@ static int do_option(int optc, const cha
+ opt->exact = true;
+ break;
+ // compression runtime parameters
++#if (WITH_UCL)
+ case 801:
+ getoptvar(&opt->crp.crp_ucl.c_flags, 0, 3, arg);
+ break;
+@@ -730,6 +733,7 @@ static int do_option(int optc, const cha
+ case 807:
+ getoptvar(&opt->crp.crp_ucl.m_size, 10000u, 999999u, arg);
+ break;
++#endif
+ case 811:
+ getoptvar(&opt->crp.crp_lzma.pos_bits, arg);
+ break;
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -57,7 +57,10 @@ ifneq ($(wildcard $(UPX_UCLDIR)/include/
+ INCLUDES += -I$(UPX_UCLDIR)/include
+ LIBS += $(addprefix -L,$(dir $(wildcard $(UPX_UCLDIR)/libucl$(libext) $(UPX_UCLDIR)/src/.libs/libucl$(libext))))
+ endif
+-LIBS += -lucl -lz
++ifeq ($(WITH_UCL),1)
++LIBS += -lucl
++endif
++LIBS += -lz
+ # you should set envvar UPX_LZMADIR to point to your unpacked LZMA SDK
+ include $(top_srcdir)/src/stub/src/c/Makevars.lzma
+ ifneq ($(UPX_LZMA_VERSION),)
+--- a/src/packer.cpp
++++ b/src/packer.cpp
+@@ -199,6 +199,7 @@ bool Packer::compress(upx_bytep i_ptr, u
+ if (cconf_parm)
+ cconf = *cconf_parm;
+ // cconf options
++#if (WITH_UCL)
+ if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))
+ {
+ if (opt->crp.crp_ucl.c_flags != -1)
+@@ -216,6 +217,7 @@ bool Packer::compress(upx_bytep i_ptr, u
+ step = 0;
+ #endif
+ }
++#endif
+ if (M_IS_LZMA(ph.method))
+ {
+ oassign(cconf.conf_lzma.pos_bits, opt->crp.crp_lzma.pos_bits);
+@@ -250,6 +252,7 @@ bool Packer::compress(upx_bytep i_ptr, u
+ if (r != UPX_E_OK)
+ throwInternalError("compression failed");
+
++#if (WITH_UCL)
+ if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method))
+ {
+ const ucl_uint *res = ph.compress_result.result_ucl.result;
+@@ -267,6 +270,7 @@ bool Packer::compress(upx_bytep i_ptr, u
+ assert(cconf.conf_ucl.max_match == 0 || cconf.conf_ucl.max_match >= ph.max_match_found);
+ }
+ }
++#endif
+
+ //printf("\nPacker::compress: %d/%d: %7d -> %7d\n", ph.method, ph.level, ph.u_len, ph.c_len);
+ if (!checkCompressionRatio(ph.u_len, ph.c_len))
+--- a/src/p_exe.cpp
++++ b/src/p_exe.cpp
+@@ -506,7 +506,9 @@ void PackExe::pack(OutputFile *fo)
+ Filter ft(ph.level);
+ // compress (max_match = 8192)
+ upx_compress_config_t cconf; cconf.reset();
++#if (WITH_UCL)
+ cconf.conf_ucl.max_match = MAXMATCH;
++#endif
+ cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
+ compressWithFilters(&ft, 32, &cconf);
+
+--- a/src/p_ps1.cpp
++++ b/src/p_ps1.cpp
+@@ -499,7 +499,9 @@ void PackPs1::pack(OutputFile *fo)
+
+ // compress (max_match = 65535)
+ upx_compress_config_t cconf; cconf.reset();
++#if (WITH_UCL)
+ cconf.conf_ucl.max_match = 65535;
++#endif
+ cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
+ compressWithFilters(&ft, sa_cnt, &cconf);
+
+--- a/src/p_tos.cpp
++++ b/src/p_tos.cpp
+@@ -506,7 +506,9 @@ void PackTos::pack(OutputFile *fo)
+ Filter ft(ph.level);
+ // compress (max_match = 65535)
+ upx_compress_config_t cconf; cconf.reset();
++#if (WITH_UCL)
+ cconf.conf_ucl.max_match = 65535;
++#endif
+ cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
+ compressWithFilters(&ft, 512, &cconf);
+
diff --git a/tools/wrt350nv2-builder/Makefile b/tools/wrt350nv2-builder/Makefile
new file mode 100644
index 0000000..a705b6d
--- /dev/null
+++ b/tools/wrt350nv2-builder/Makefile
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2006-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wrt350nv2-builder
+PKG_VERSION:=2.4
+PKG_REVISION:=2
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/${PKG_NAME}-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(HOSTCC) $(HOST_CFLAGS) -c src/md5.c -o $(HOST_BUILD_DIR)/md5.o
+ $(HOSTCC) $(HOST_CFLAGS) -c src/ioapi.c -o $(HOST_BUILD_DIR)/ioapi.o
+ $(HOSTCC) $(HOST_CFLAGS) -c src/wrt350nv2-builder.c -o $(HOST_BUILD_DIR)/wrt350nv2-builder.o
+ $(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $(HOST_BUILD_DIR)/wrt350nv2-builder \
+ $(HOST_BUILD_DIR)/wrt350nv2-builder.o $(HOST_BUILD_DIR)/md5.o $(HOST_BUILD_DIR)/ioapi.o
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/wrt350nv2-builder $(STAGING_DIR_HOST)/bin/
+# optionally the builder can add a u-boot binary to create a complete webupgrade image, but this is not mandatory
+# u-boot images from stock firmware are available at ftp://ftp.maddes.net/openwrt/trunk/orion/stock/binaries/
+ [ ! -f "files/u-boot.bin" ] || ( \
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/share/wrt350nv2-builder; \
+ $(CP) files/u-boot.bin $(STAGING_DIR_HOST)/share/wrt350nv2-builder/; )
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/wrt350nv2-builder
+ rm -f $(STAGING_DIR_HOST)/share/wrt350nv2-builder
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/wrt350nv2-builder/src/crypt.h b/tools/wrt350nv2-builder/src/crypt.h
new file mode 100644
index 0000000..622f4bc
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/crypt.h
@@ -0,0 +1,132 @@
+/* crypt.h -- base code for crypt/uncrypt ZIPfile
+
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This code is a modified version of crypting code in Infozip distribution
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ If you don't need crypting in your application, just define symbols
+ NOCRYPT and NOUNCRYPT.
+
+ This code support the "Traditional PKWARE Encryption".
+
+ The new AES encryption added on Zip format by Winzip (see the page
+ http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
+ Encryption is not supported.
+*/
+
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+{
+ unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
+ * unpredictable manner on 16-bit systems; not a problem
+ * with any known compiler so far, though */
+
+ temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
+ return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+{
+ (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
+ (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+ (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+ {
+ register int keyshift = (int)((*(pkeys+1)) >> 24);
+ (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+ }
+ return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+{
+ *(pkeys+0) = 305419896L;
+ *(pkeys+1) = 591751049L;
+ *(pkeys+2) = 878082192L;
+ while (*passwd != '\0') {
+ update_keys(pkeys,pcrc_32_tab,(int)*passwd);
+ passwd++;
+ }
+}
+
+#define zdecode(pkeys,pcrc_32_tab,c) \
+ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
+
+#define zencode(pkeys,pcrc_32_tab,c,t) \
+ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+
+#define RAND_HEAD_LEN 12
+ /* "last resort" source for second part of crypt seed pattern */
+# ifndef ZCR_SEED2
+# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
+# endif
+
+static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
+ const char *passwd; /* password string */
+ unsigned char *buf; /* where to write header */
+ int bufSize;
+ unsigned long* pkeys;
+ const unsigned long* pcrc_32_tab;
+ unsigned long crcForCrypting;
+{
+ int n; /* index in random header */
+ int t; /* temporary */
+ int c; /* random byte */
+ unsigned char header[RAND_HEAD_LEN-2]; /* random header */
+ static unsigned calls = 0; /* ensure different random header each time */
+
+ if (bufSize<RAND_HEAD_LEN)
+ return 0;
+
+ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+ * output of rand() to get less predictability, since rand() is
+ * often poorly implemented.
+ */
+ if (++calls == 1)
+ {
+ srand((unsigned)(time(NULL) ^ ZCR_SEED2));
+ }
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ c = (rand() >> 7) & 0xff;
+ header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
+ }
+ /* Encrypt random header (last two bytes is high word of crc) */
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
+ }
+ buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+ buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+ return n;
+}
+
+#endif
diff --git a/tools/wrt350nv2-builder/src/ioapi.c b/tools/wrt350nv2-builder/src/ioapi.c
new file mode 100644
index 0000000..f1bee23
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/ioapi.c
@@ -0,0 +1,177 @@
+/* ioapi.c -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+#include "ioapi.h"
+
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+voidpf ZCALLBACK fopen_file_func OF((
+ voidpf opaque,
+ const char* filename,
+ int mode));
+
+uLong ZCALLBACK fread_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ void* buf,
+ uLong size));
+
+uLong ZCALLBACK fwrite_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ const void* buf,
+ uLong size));
+
+long ZCALLBACK ftell_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+long ZCALLBACK fseek_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ uLong offset,
+ int origin));
+
+int ZCALLBACK fclose_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+int ZCALLBACK ferror_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
+ voidpf opaque;
+ const char* filename;
+ int mode;
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ void* buf;
+ uLong size;
+{
+ uLong ret;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ const void* buf;
+ uLong size;
+{
+ uLong ret;
+ ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+long ZCALLBACK ftell_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ long ret;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
+ voidpf opaque;
+ voidpf stream;
+ uLong offset;
+ int origin;
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ fseek((FILE *)stream, offset, fseek_origin);
+ return ret;
+}
+
+int ZCALLBACK fclose_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+int ZCALLBACK ferror_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/tools/wrt350nv2-builder/src/ioapi.h b/tools/wrt350nv2-builder/src/ioapi.h
new file mode 100644
index 0000000..5fa9786
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/ioapi.h
@@ -0,0 +1,75 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+#ifndef _ZLIBIOAPI_H
+#define _ZLIBIOAPI_H
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+
+#ifndef ZCALLBACK
+
+#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+#define ZCALLBACK CALLBACK
+#else
+#define ZCALLBACK
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
+typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
+typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size);
+typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
+typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
+typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
+typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
+
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+
+
+void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def);
+
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tools/wrt350nv2-builder/src/md5.c b/tools/wrt350nv2-builder/src/md5.c
new file mode 100644
index 0000000..c35d96c
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/md5.c
@@ -0,0 +1,381 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/tools/wrt350nv2-builder/src/md5.h b/tools/wrt350nv2-builder/src/md5.h
new file mode 100644
index 0000000..698c995
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/md5.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/tools/wrt350nv2-builder/src/upgrade.h b/tools/wrt350nv2-builder/src/upgrade.h
new file mode 100644
index 0000000..2b5953a
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/upgrade.h
@@ -0,0 +1,77 @@
+#ifndef _UPGRADE_H_
+#define _UPGRADE_H_
+
+#define FLASH_END_ADDR 0xffffffff
+#define FLASH_ADDR_BASE 0xff800000
+#define BOOT_ADDR_BASE 0xfffc0000
+#define BOOT_ADDR_BASE_OFF 0x7c0000
+#define FLASH_SIZE 0x800000
+#define BOOT_SIZE 0x40000
+//NVRAM in boot area
+//#define NVRAM_ADDR_BASE 0xfff90000
+//#define NVRAM_ADDR_BASE_OFF 0x790000
+//#define NVRAM_SIZE 0x10000
+
+#define PID_OFFSET (BOOT_SIZE- 0x46)
+#define NODE_ADDRESS (BOOT_SIZE-0x60)
+#define NODE_BASE_OFF (FLASH_SIZE-0x60)
+#define PIN_ADDRESS (BOOT_SIZE-0x70)//WPS PIN,8bytes
+#define PIN_OFF (FLASH_SIZE-0x70)
+#define KERNEL_CODE_OFFSET 0
+#define SN_ADDRESS (BOOT_SIZE-0x80) //12bytes
+#define SN_OFF (FLASH_SIZE-0x80)
+
+
+#define UPGRADE_START_OFFSET 0
+#define UPGRADE_END_OFFSET 0x7A0000
+#define PRODUCT_ID_OFFSET 0x75ffe0//(UPGRADE_END_OFFSET - 0x10)
+#define PROTOCOL_ID_OFFSET (PRODUCT_ID_OFFSET + 0x02)
+#define FW_VERSION_OFFSET (PRODUCT_ID_OFFSET + 0x04)
+#define SIGN_OFFSET (PRODUCT_ID_OFFSET + 0x08) /* eRcOmM */
+
+//#define LANG_UPGRADE
+#ifdef LANG_UPGRADE
+#define LANGBUF_BEGIN 0x1300000
+#define LANGBUF_END 0x1f00000
+#define LANGBUF_LENTH (LANGBUF_END - LANGBUF_BEGIN)
+#endif
+#ifndef ERROR
+#define ERROR -1
+#endif
+
+#ifndef OK
+#define OK 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+void do_boot(void);
+void Download(void);
+void Assign(void);
+
+void gpio_init(void);
+void Led_Power(int value);
+void Led_security(int value);
+int PushButton(void);
+
+static unsigned short xchg ( unsigned short dwData);
+int FlashDriver(unsigned long dlAddress,unsigned char *dbData,unsigned long dlLength,unsigned long dlFlag);
+int ProgramChip(unsigned long dlAddress,unsigned char * dbData,unsigned long dlLength);
+int dl_Initialize(void);
+void dl_GetAddr(unsigned char *node);
+int dl_Receive(void);
+int dl_Transmit(char *buf,int len);
+void reset(void);
+void AssignHWAddress(unsigned char *psBuffer);
+int ResetChip(unsigned long ulRomDstAddr);
+int GetFlashType(void);
+
+#ifdef LANG_UPGRADE
+int save_lang_buf(unsigned long flash_addr, char *mem_addr,unsigned long length);
+int LangDriver(unsigned long flash_addr, char *mem_addr,unsigned long length, unsigned long dlFlag);
+#endif
+#endif
+
diff --git a/tools/wrt350nv2-builder/src/wrt350nv2-builder.c b/tools/wrt350nv2-builder/src/wrt350nv2-builder.c
new file mode 100644
index 0000000..3ebb40e
--- /dev/null
+++ b/tools/wrt350nv2-builder/src/wrt350nv2-builder.c
@@ -0,0 +1,1126 @@
+/*
+
+ WRT350Nv2-Builder 2.4 (previously called buildimg)
+ Copyright (C) 2008-2009 Dirk Teurlings <info@upexia.nl>
+ Copyright (C) 2009-2011 Matthias Buecher (http://www.maddes.net/)
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A lot of thanks to Kaloz and juhosg from OpenWRT and Lennert Buytenhek from
+ marvell for helping me figure this one out. This code is based on bash
+ scripts wrote by Peter van Valderen so the real credit should go to him.
+
+ This program reads the provided parameter file and creates an image which can
+ be used to flash a Linksys WRT350N v2 from stock firmware.
+ The trick is to fill unused space in the bin file with random, so that the
+ resulting zip file passes the size check of the stock firmware.
+
+ The parameter file layout for an original Linksys firmware:
+ :kernel 0x001A0000 /path/to/uImage
+ :rootfs 0 /path/to/root.squashfs
+ :u-boot 0 /path/to/u-boot.bin
+ #version 0x2020
+
+ Additionally since v2.4 an already complete image can be used:
+ :image 0 /path/to/openwrt-wrt350nv2-[squashfs|jffs2-64k].img
+
+ args:
+ 1 wrt350nv2.par parameter file describing the image layout
+ 2 wrt350nv2.img output file for linksys style image
+
+ A u-boot image inside the bin file is not necessary.
+ The version is not important.
+ The name of the bin file is not important, but still "wrt350n.bin" is used to
+ keep as close as possible to the stock firmware.
+
+ Linksys assumes that no mtd will be used to its maximum, so the last 16 bytes
+ of the mtd are abused to define the length of the next mtd content (4 bytes for
+ size + 12 pad bytes).
+
+ At the end of "rootfs" additional 16 bytes are abused for some data and a
+ highly important eRcOmM identifier, so the last 32 bytes of "rootfs" are abused.
+
+ At the end of "u-boot" 128 bytes are abused for some data, a checksum and a
+ highly important sErCoMm identifier.
+
+
+ This program uses a special GNU scanf modifier to allocate
+ sufficient memory for a strings with unknown length.
+ See http://www.kernel.org/doc/man-pages/online/pages/man3/scanf.3.html#NOTES
+
+
+ To extract everything from a Linksys style firmware image see
+ https://forum.openwrt.org/viewtopic.php?pid=92928#p92928
+
+ Changelog:
+ v2.4 - added ":image" definition for parameter file, this allows
+ to use a complete sysupgrade image without any kernel size check
+ v2.3 - allow jffs by adding its magic number (0x8519)
+ added parameter option -i to ignore unknown magic numbers
+ v2.2 - fixed checksum byte calculation for other versions than 0x2019
+ fixed rare problem with padsize
+ updated info to stock firmware 2.00.20
+ fixed typos
+ v2.1 - used "wrt350n.bin" for the created image (closer to stock)
+ added option to create the image in two separate steps (-b / -z)
+ v2.0 - complete re-write
+
+*/
+
+// includes
+#define _GNU_SOURCE // for GNU's basename()
+#include <assert.h>
+#include <errno.h> // errno
+#include <stdarg.h>
+#include <stdio.h> // fopen(), fread(), fclose(), etc.
+#include <stdlib.h> // system(), etc.
+#include <string.h> // basename(), strerror(), strdup(), etc.
+#include <unistd.h> // optopt(), access(), etc.
+#include <libgen.h>
+#include <sys/wait.h> // WEXITSTATUS, etc.
+
+// custom includes
+#include "md5.h" // MD5 routines
+#include "upgrade.h" // Linksys definitions from firmware 2.0.19 (unchanged up to 2.0.20)
+
+
+// version info
+#define VERSION "2.4"
+char program_info[] = "WRT350Nv2-Builder v%s by Dirk Teurlings <info@upexia.nl> and Matthias Buecher (http://www.maddes.net/)\n";
+
+// verbosity
+#define DEBUG 1
+#define DEBUG_LVL2 2
+int verbosity = 0;
+
+// mtd info
+typedef struct {
+ char *name;
+ int offset;
+ int size;
+ char *filename;
+ long int filesize;
+ unsigned char magic[2];
+} mtd_info;
+
+mtd_info mtd_kernel = { "kernel", 0, 0, NULL, 0L, { 0, 0 } };
+mtd_info mtd_rootfs = { "rootfs", 0, 0, NULL, 0L, { 0, 0 } };
+mtd_info mtd_image = { "image", 0, 0, NULL, 0L, { 0, 0 } };
+mtd_info mtd_uboot = { "u-boot", 0, 0, NULL, 0L, { 0, 0 } };
+
+#define ROOTFS_END_OFFSET 0x00760000
+#define ROOTFS_MIN_OFFSET 0x00640000 // should be filled up to here, to make sure that the zip file is big enough to pass the size check of the stock firmware
+ // 2.0.17: filled up to 0x00640000
+ // 2.0.19: filled up to 0x00670000
+ // 2.0.20: filled up to 0x00670000
+
+// rootfs statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0x0075FFE0 -n 16 "wrt350n.bin" ; echo -en "\n"
+unsigned char product_id[] = { 0x00, 0x03 }; // seems to be a fixed value
+unsigned char protocol_id[] = { 0x00, 0x00 }; // seems to be a fixed value
+unsigned char fw_version[] = { 0x20, 0x20 };
+unsigned char rootfs_unknown[] = { 0x90, 0xF7 }; // seems to be a fixed value
+unsigned char sign[] = { 0x65, 0x52, 0x63, 0x4F, 0x6D, 0x4D, 0x00, 0x00 }; // eRcOmM
+
+// u-boot statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0x007FFF80 -n 128 "wrt350n.bin" ; echo -en "\n"
+//unsigned char sn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // (12) seems to be an unused value
+//unsigned char pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // (8) seems to be an unused value
+//unsigned char node[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (25) seems to be an unused value
+// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+//unsigned char checksum[] = { 0xE9 }; // (1) is calculated, does it belong to node?
+unsigned char pid[] = { 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x01, 0x00, 0x00, 0x59, 0x42, 0x50, 0x00, 0x01, // (70) seems to be a fixed value, except for fw version
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, // protocol id?
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // protocol id?
+ 0x12, 0x34, // firmware version, same as in rootfs
+ 0x00, 0x00, 0x00, 0x04,
+ 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D }; // sErCoMm
+
+// img statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0 -n 512 "WRT350N-EU-ETSI-2.00.19.img" ; echo -en "\n" (unchanged up to 2.0.20)
+unsigned char img_hdr[] = { 0x00, 0x01, 0x00, 0x00, 0x59, 0x42, 0x50, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00,
+ 0x12, 0x34, // firmware version, same as in rootfs
+ 0x00, 0x00, 0x00, 0x04, 0x61, 0x44, 0x6D, 0x42, 0x6C, 0x4B, 0x3D, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, // md5 checksum
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+unsigned char img_eof[] = { 0xFF };
+
+
+void lprintf(int outputlevel, char *fmt, ...) {
+ va_list argp;
+ if (outputlevel <= verbosity) {
+ va_start(argp, fmt);
+ vprintf(fmt, argp);
+ va_end(argp);
+ }
+}
+
+
+int parse_par_file(FILE *f_par) {
+ int exitcode = 0;
+
+ char *buffer;
+ size_t buffer_size;
+ char *line;
+
+ int lineno;
+ int count;
+
+ char string1[256];
+ char string2[256];
+ int value;
+
+ mtd_info *mtd;
+ FILE *f_in;
+ int f_exitcode = 0;
+
+ // read all lines
+ buffer_size = 1000;
+ buffer = NULL;
+ lineno = 0;
+ while (!feof(f_par)) {
+ // read next line into memory
+ do {
+ // allocate memory for input line
+ if (!buffer) {
+ buffer = malloc(buffer_size);
+ }
+ if (!buffer) {
+ exitcode = 1;
+ printf("parse_par_file: can not allocate %i bytes\n", (int) buffer_size);
+ break;
+ }
+
+ line = fgets(buffer, buffer_size, f_par);
+ if (!line) {
+ exitcode = ferror(f_par);
+ if (exitcode) {
+ printf("parse_par_file: %s\n", strerror(exitcode));
+ }
+ break;
+ }
+
+ // if buffer was not completely filled, then assume that line is complete
+ count = strlen(buffer) + 1;
+ if (count-- < buffer_size) {
+ break;
+ }
+
+ // otherwise....
+
+ // reset file position to line start
+ value = fseek(f_par, -count, SEEK_CUR);
+ if (value == -1) {
+ exitcode = errno;
+ printf("parse_par_file: %s\n", strerror(exitcode));
+ break;
+ }
+
+ // double buffer size
+ free(buffer);
+ buffer = NULL;
+ buffer_size *= 2;
+ lprintf(DEBUG_LVL2, " extending buffer to %i bytes\n", buffer_size);
+ } while (1);
+ if ((!line) || (exitcode)) {
+ break;
+ }
+
+ lineno++; // increase line number
+
+ lprintf(DEBUG_LVL2, " line %i (%i) %s", lineno, count, line);
+
+ value = 0;
+ mtd = NULL;
+
+ // split line if starting with a colon
+ switch (line[0]) {
+ case ':':
+ count = sscanf(line, ":%255s %i %255s", string1, &value, string2);
+ if (count != 3) {
+ printf("line %i does not meet defined format (:<mtdname> <mtdsize> <file>)\n", lineno);
+ } else {
+ // populate mtd_info if supported mtd names
+ if (!strcmp(string1, mtd_kernel.name)) {
+ mtd = &mtd_kernel;
+ } else if (!strcmp(string1, mtd_rootfs.name)) {
+ mtd = &mtd_rootfs;
+ } else if (!strcmp(string1, mtd_uboot.name)) {
+ mtd = &mtd_uboot;
+ } else if (!strcmp(string1, mtd_image.name)) {
+ mtd = &mtd_image;
+ }
+
+ if (!mtd) {
+ printf("unknown mtd %s in line %i\n", string1, lineno);
+ } else if (mtd->filename) {
+ f_exitcode = 1;
+ printf("mtd %s in line %i multiple definitions\n", string1, lineno);
+ } else {
+ mtd->size = value;
+ mtd->filename = strdup(string2);
+
+ // Get file size
+ f_in = fopen(mtd->filename, "rb");
+ if (!f_in) {
+ f_exitcode = errno;
+ printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
+ } else {
+ value = fread(&mtd->magic, 1, 2, f_in);
+ if (value < 2) {
+ if (ferror(f_in)) {
+ f_exitcode = ferror(f_in);
+ printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
+ } else {
+ f_exitcode = 1;
+ printf("input file %s: smaller than two bytes, no magic code\n", mtd->filename);
+ }
+ }
+
+ value = fseek(f_in, 0, SEEK_END);
+ if (value == -1) {
+ f_exitcode = errno;
+ printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
+ } else {
+ mtd->filesize = ftell(f_in);
+ if (mtd->filesize == -1) {
+ f_exitcode = errno;
+ printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
+ }
+ }
+
+ fclose(f_in);
+ }
+
+ lprintf(DEBUG, "mtd %s in line %i: size=0x%08X, filesize=0x%08lX, magic=0x%02X%02X, file=%s\n", mtd->name, lineno, mtd->size, mtd->filesize, mtd->magic[0], mtd->magic[1], mtd->filename);
+ }
+ }
+ break;
+ case '#': // integer values
+ count = sscanf(line, "#%255s %i", string1, &value);
+ if (count != 2) {
+ printf("line %i does not meet defined format (#<variable name> <integer>\n", lineno);
+ } else {
+ if (!strcmp(string1, "version")) {
+ // changing version
+ fw_version[0] = 0x000000FF & ( value >> 8 );
+ fw_version[1] = 0x000000FF & value;
+ } else {
+ printf("unknown integer variable %s in line %i\n", string1, lineno);
+ }
+
+ lprintf(DEBUG, "integer variable %s in line %i: 0x%08X\n", string1, lineno, value);
+ }
+ break;
+ case '$': // strings
+ count = sscanf(line, "$%255s %255s", string1, string2);
+ if (count != 2) {
+ printf("line %i does not meet defined format (:<mtdname> <mtdsize> <file>)\n", lineno);
+ } else {
+/*
+ if (!strcmp(string1, "something")) {
+ something = strdup(string2);
+ } else {
+*/
+ printf("unknown string variable %s in line %i\n", string1, lineno);
+// }
+ lprintf(DEBUG, "string variable %s in line %i: %s\n", string1, lineno, string2);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ free(buffer);
+
+ if (!exitcode) {
+ exitcode = f_exitcode;
+ }
+
+ return exitcode;
+}
+
+
+int create_bin_file(char *bin_filename) {
+ int exitcode = 0;
+
+ unsigned char *buffer;
+
+ int i;
+ mtd_info *mtd;
+ int addsize;
+ int padsize;
+
+ char *rand_filename = "/dev/urandom";
+ FILE *f_in;
+ int size;
+
+ unsigned long int csum;
+ unsigned char checksum;
+
+ FILE *f_out;
+
+ // allocate memory for bin file
+ buffer = malloc(KERNEL_CODE_OFFSET + FLASH_SIZE);
+ if (!buffer) {
+ exitcode = 1;
+ printf("create_bin_file: can not allocate %i bytes\n", FLASH_SIZE);
+ } else {
+ // initialize with zero
+ memset(buffer, 0, KERNEL_CODE_OFFSET + FLASH_SIZE);
+ }
+
+ // add files
+ if (!exitcode) {
+ for (i = 1; i <= 4; i++) {
+ addsize = 0;
+ padsize = 0;
+
+ switch (i) {
+ case 1:
+ mtd = &mtd_image;
+ padsize = ROOTFS_MIN_OFFSET - mtd->filesize;
+ break;
+ case 2:
+ mtd = &mtd_kernel;
+ break;
+ case 3:
+ mtd = &mtd_rootfs;
+ addsize = mtd->filesize;
+ padsize = ROOTFS_MIN_OFFSET - mtd_kernel.size - mtd->filesize;
+ break;
+ case 4:
+ mtd = &mtd_uboot;
+ addsize = mtd->filesize;
+ break;
+ default:
+ mtd = NULL;
+ exitcode = 1;
+ printf("create_bin_file: unknown mtd %i\n", i);
+ break;
+ }
+ if (!mtd) {
+ break;
+ }
+ if (!mtd->filename) {
+ continue;
+ }
+
+ lprintf(DEBUG, "adding mtd %s file %s\n", mtd->name, mtd->filename);
+
+ // adding file size
+ if (addsize) {
+ buffer[KERNEL_CODE_OFFSET + mtd->offset - 16] = 0x000000FFL & ( addsize >> 24 );
+ buffer[KERNEL_CODE_OFFSET + mtd->offset - 15] = 0x000000FFL & ( addsize >> 16 );
+ buffer[KERNEL_CODE_OFFSET + mtd->offset - 14] = 0x000000FFL & ( addsize >> 8 );
+ buffer[KERNEL_CODE_OFFSET + mtd->offset - 13] = 0x000000FFL & addsize;
+ }
+
+ // adding file content
+ f_in = fopen(mtd->filename, "rb");
+ if (!f_in) {
+ exitcode = errno;
+ printf("input file %s: %s\n", mtd->filename, strerror(exitcode));
+ } else {
+ size = fread(&buffer[KERNEL_CODE_OFFSET + mtd->offset], mtd->filesize, 1, f_in);
+ if (size < 1) {
+ if (ferror(f_in)) {
+ exitcode = ferror(f_in);
+ printf("input file %s: %s\n", mtd->filename, strerror(exitcode));
+ } else {
+ exitcode = 1;
+ printf("input file %s: smaller than before *doh*\n", mtd->filename);
+ }
+ }
+ fclose(f_in);
+ }
+
+ // padding
+ if (padsize > 0) {
+ addsize = padsize & 0x0000FFFF; // start on next 64KB border
+ padsize -= addsize;
+ }
+ if (padsize > 0) {
+ printf("mtd %s input file %s is too small (0x%08lX), adding 0x%08X random bytes\n", mtd->name, mtd->filename, mtd->filesize, padsize);
+
+ addsize += KERNEL_CODE_OFFSET + mtd->offset + mtd->filesize; // get offset
+ lprintf(DEBUG, " padding offset 0x%08X length 0x%08X\n", addsize, padsize);
+
+ f_in = fopen(rand_filename, "rb");
+ if (!f_in) {
+ exitcode = errno;
+ printf("input file %s: %s\n", rand_filename, strerror(exitcode));
+ } else {
+ size = fread(&buffer[addsize], padsize, 1, f_in);
+ if (size < 1) {
+ if (ferror(f_in)) {
+ exitcode = ferror(f_in);
+ printf("input file %s: %s\n", rand_filename, strerror(exitcode));
+ } else {
+ exitcode = 1;
+ printf("input file %s: smaller than before *doh*\n", rand_filename);
+ }
+ }
+ }
+ fclose(f_in);
+ }
+ }
+ }
+
+ // add special contents
+ if (!exitcode) {
+ lprintf(DEBUG, "adding rootfs special data\n");
+ memcpy(&buffer[KERNEL_CODE_OFFSET + PRODUCT_ID_OFFSET], product_id, 2);
+ memcpy(&buffer[KERNEL_CODE_OFFSET + PROTOCOL_ID_OFFSET], protocol_id, 2);
+ memcpy(&buffer[KERNEL_CODE_OFFSET + FW_VERSION_OFFSET], fw_version, 2);
+ memcpy(&buffer[KERNEL_CODE_OFFSET + FW_VERSION_OFFSET + 2], rootfs_unknown, 2);
+ memcpy(&buffer[KERNEL_CODE_OFFSET + SIGN_OFFSET], sign, 8); // eRcOmM
+
+ lprintf(DEBUG, "adding u-boot special data\n");
+// memcpy(&buffer[KERNEL_CODE_OFFSET + SN_OFF], sn, 12); // ToDo: currently zero, find out what's this for?
+// memcpy(&buffer[KERNEL_CODE_OFFSET + PIN_OFF], pin, 8); // ToDo: currently zero, find out what's this for?
+// memcpy(&buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF], node, 25); // ToDo: currently zero, find out what's this for?
+ memcpy(&buffer[KERNEL_CODE_OFFSET + BOOT_ADDR_BASE_OFF + PID_OFFSET], pid, 70); // sErCoMm
+ memcpy(&buffer[KERNEL_CODE_OFFSET + BOOT_ADDR_BASE_OFF + PID_OFFSET + 57], fw_version, 2);
+
+ lprintf(DEBUG, "adding checksum byte\n");
+ csum = 0;
+ for (i = 0; i < KERNEL_CODE_OFFSET + FLASH_SIZE; i++) {
+ csum += buffer[i];
+ }
+ lprintf(DEBUG_LVL2, " checksum 0x%016lX (%li)\n", csum, csum);
+
+ buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF + 25] = ~csum + 1;
+ lprintf(DEBUG, " byte 0x%02X\n", buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF + 25]);
+ }
+
+ // write bin file
+ if (!exitcode) {
+ lprintf(DEBUG, "writing file %s\n", bin_filename);
+ f_out = fopen(bin_filename, "wb");
+ if (!f_out) {
+ exitcode = errno;
+ printf("output file %s: %s\n", bin_filename, strerror(exitcode));
+ } else {
+ size = fwrite(buffer, KERNEL_CODE_OFFSET + FLASH_SIZE, 1, f_out);
+ if (size < 1) {
+ if (ferror(f_out)) {
+ exitcode = ferror(f_out);
+ printf("output file %s: %s\n", bin_filename, strerror(exitcode));
+ } else {
+ exitcode = 1;
+ printf("output file %s: unspecified write error\n", bin_filename);
+ }
+ }
+ fclose(f_out);
+ }
+ }
+
+ return exitcode;
+}
+
+
+int create_zip_file(char *zip_filename, char *bin_filename) {
+ int exitcode = 0;
+
+ char *buffer;
+ size_t buffer_size;
+ int count;
+
+ buffer_size = 1000;
+ buffer = NULL;
+ do {
+ // allocate memory for command line
+ if (!buffer) {
+ buffer = malloc(buffer_size);
+ }
+ if (!buffer) {
+ exitcode = 1;
+ printf("create_zip_file: can not allocate %i bytes\n", (int) buffer_size);
+ break;
+ }
+
+ // if buffer was not completely filled, then line fit in completely
+ count = snprintf(buffer, buffer_size, "zip \"%s\" \"%s\"", zip_filename, bin_filename);
+ if ((count > -1) && (count < buffer_size)) {
+ break;
+ }
+
+ // otherwise try again with more space
+ if (count > -1) { // glibc 2.1
+ buffer_size = count + 1; // precisely what is needed
+ } else { // glibc 2.0
+ buffer_size *= 2; // twice the old size
+ }
+ free(buffer);
+ buffer = NULL;
+ lprintf(DEBUG_LVL2, " extending buffer to %i bytes\n", buffer_size);
+ } while (1);
+
+ if (!exitcode) {
+ // zipping binfile
+ lprintf(DEBUG, "%s\n", buffer);
+ count = system(buffer);
+ if ((count < 0) || (WEXITSTATUS(count))) {
+ exitcode = 1;
+ printf("create_zip_file: can not execute %s bytes\n", buffer);
+ }
+ }
+
+ return exitcode;
+}
+
+
+int create_img_file(FILE *f_out, char *out_filename, char *zip_filename) {
+ int exitcode = 0;
+
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ int i;
+ int size;
+
+ FILE *f_in;
+ unsigned char buffer[1];
+
+ // copy firmware version
+ memcpy(&img_hdr[50], fw_version, 2);
+
+ // clear md5 checksum
+ memset(&img_hdr[480], 0, 16);
+
+ // prepare md5 checksum calculation
+ md5_init(&state);
+
+ // add img header
+ lprintf(DEBUG_LVL2, " adding img header\n");
+ for (i = 0; i < 512; i++) {
+ size = fputc(img_hdr[i], f_out);
+ if (size == EOF) {
+ exitcode = ferror(f_out);
+ printf("output file %s: %s\n", out_filename, strerror(exitcode));
+ break;
+ }
+ md5_append(&state, (const md5_byte_t *)&img_hdr[i], 1);
+ }
+
+ // adding zip file
+ if (!exitcode) {
+ lprintf(DEBUG_LVL2, " adding zip file\n");
+ f_in = fopen(zip_filename, "rb");
+ if (!f_in) {
+ exitcode = errno;
+ printf("input file %s: %s\n", zip_filename, strerror(exitcode));
+ } else {
+ while ((size = fgetc(f_in)) != EOF) {
+ buffer[0] = size;
+
+ size = fputc(buffer[0], f_out);
+ if (size == EOF) {
+ exitcode = ferror(f_out);
+ printf("output file %s: %s\n", out_filename, strerror(exitcode));
+ break;
+ }
+ md5_append(&state, (const md5_byte_t *)buffer, 1);
+ }
+ if (ferror(f_in)) {
+ exitcode = ferror(f_in);
+ printf("input file %s: %s\n", zip_filename, strerror(exitcode));
+ }
+ }
+
+ }
+
+ // add end byte
+ if (!exitcode) {
+ lprintf(DEBUG_LVL2, " adding img eof byte\n");
+ size = fputc(img_eof[0], f_out);
+ if (size == EOF) {
+ exitcode = ferror(f_out);
+ printf("output file %s: %s\n", out_filename, strerror(exitcode));
+ }
+ md5_append(&state, (const md5_byte_t *)img_eof, 1);
+ }
+
+ // append salt to md5 checksum
+ md5_append(&state, (const md5_byte_t *)"A^gU*<>?RFY@#DR&Z", 17);
+
+ // finish md5 checksum calculation
+ md5_finish(&state, digest);
+
+ // write md5 checksum into img header
+ if (!exitcode) {
+ lprintf(DEBUG_LVL2, " writing md5 checksum into img header of file\n");
+
+ size = fseek(f_out, 480, SEEK_SET);
+ if (size == -1) {
+ exitcode = errno;
+ printf("output file %s: %s\n", out_filename, strerror(exitcode));
+ } else {
+ size = fwrite(digest, 16, 1, f_out);
+ if (size < 1) {
+ if (ferror(f_out)) {
+ exitcode = ferror(f_out);
+ printf("output file %s: %s\n", out_filename, strerror(exitcode));
+ } else {
+ exitcode = 1;
+ printf("output file %s: unspecified write error\n", out_filename);
+ }
+ }
+ }
+
+ fclose(f_in);
+ }
+
+ return exitcode;
+}
+
+
+int main(int argc, char *argv[]) {
+ int exitcode = 0;
+
+ int help;
+ int onlybin;
+ int havezip;
+ int ignoremagic;
+ char option;
+ char *par_filename = NULL;
+ char *img_filename = NULL;
+ char *base_filename = NULL;
+ char *bin_filename = NULL;
+ char *zip_filename = NULL;
+
+ FILE *f_par = NULL;
+ FILE *f_img = NULL;
+
+ int i;
+ mtd_info *mtd;
+ int noupdate;
+ int sizecheck;
+ int magiccheck;
+ int magicerror;
+
+
+// display program header
+ printf(program_info, VERSION);
+
+
+// command line processing
+ // options
+ help = 0;
+ onlybin = 0;
+ havezip = 0;
+ ignoremagic = 0;
+ while ((option = getopt(argc, argv, "hbzif:v")) != -1) {
+ switch(option) {
+ case 'h':
+ help = 1;
+ break;
+ case 'b':
+ onlybin = 1;
+ break;
+ case 'z':
+ havezip = 1;
+ break;
+ case 'i':
+ ignoremagic = 1;
+ break;
+ case 'f':
+ sizecheck = sscanf(optarg, "%i", &i);
+ if (sizecheck != 1) {
+ printf("Firmware version of -f option not a valid integer\n");
+ exitcode = 1;
+ } else {
+ fw_version[0] = 0x000000FF & ( i >> 8 );
+ fw_version[1] = 0x000000FF & i;
+ }
+ break;
+ case 'v':
+ verbosity++;
+ break;
+ case ':': // option with missing operand
+ printf("Option -%c requires an operand\n", optopt);
+ exitcode = 1;
+ break;
+ case '?':
+ printf("Unrecognized option: -%c\n", optopt);
+ exitcode = 1;
+ break;
+ }
+ }
+
+ // files
+ for ( ; optind < argc; optind++) {
+ if (!par_filename) {
+ par_filename = argv[optind];
+
+ if (access(par_filename, R_OK)) {
+ if (havezip) {
+ printf("No read access to zip file %s\n", par_filename);
+ } else {
+ printf("No read access to parameter or zip file %s\n", par_filename);
+ }
+ exitcode = 1;
+ }
+
+ continue;
+ }
+
+ if ((!onlybin) && (!img_filename)) {
+ img_filename = argv[optind];
+
+ if (!access(img_filename, F_OK)) { // if file already exists then check write access
+ if (access(img_filename, W_OK)) {
+ printf("No write access to image file %s\n", img_filename);
+ exitcode = 1;
+ }
+ }
+
+ continue;
+ }
+
+ printf("Too many files stated\n");
+ exitcode = 1;
+ break;
+ }
+
+ // file name checks
+ if (!par_filename) {
+ if (havezip) {
+ printf("Zip file not stated\n");
+ } else {
+ printf("Parameter file not stated\n");
+ }
+ exitcode = 1;
+ } else {
+ base_filename = basename(par_filename);
+ if (!base_filename) {
+ if (havezip) {
+ printf("Zip file is a directory\n");
+ } else {
+ printf("Parameter file is a directory\n");
+ }
+ exitcode = 1;
+ }
+ }
+
+ if (!onlybin) {
+ if (!img_filename) {
+ printf("Image file not stated\n");
+ exitcode = 1;
+ } else {
+ base_filename = basename(img_filename);
+ if (!base_filename) {
+ printf("Image file is a directory\n");
+ exitcode = 1;
+ }
+ }
+ }
+
+ // check for mutually exclusive options
+ if ((onlybin) && (havezip)) {
+ printf("Option -b and -z are mutually exclusive\n");
+ exitcode = 1;
+ }
+
+ // react on option problems or help request, then exit
+ if ((exitcode) || (help)) {
+ if (help) {
+ printf("This program creates Linksys style images for the WRT350Nv2 router.\n");
+ }
+ printf(" Usage:\n\
+ %s [-h] [-b] [-z] [-i] [-f <version>] [-v] <parameter or zip file> [<image file>]\n\n\
+ Options:\n\
+ -h - Show this help\n\
+ -b - Create only bin file, no img or zip file is created\n\
+ -z - Have zip file, the img file will be directly created from it\n\
+ -i - Ignore unknown magic numbers\n\
+ -f <version> - Wanted firmware version to use with -z\n\
+ Default firmware version is 0x2020 = 2.00.20.\n\
+ Note: version from parameter file will supersede this\n\
+ -v - Increase debug verbosity level\n\n\
+ Example:\n\
+ %s wrt350nv2.par wrt350nv2.img\n\n", argv[0], argv[0]);
+ return exitcode;
+ }
+
+ // handle special case when zipfile is stated
+ if (havezip) {
+ zip_filename = par_filename;
+ par_filename = NULL;
+ }
+
+ lprintf(DEBUG_LVL2, " Verbosity: %i\n", verbosity);
+ lprintf(DEBUG_LVL2, " Program: %s\n", argv[0]);
+
+ if (par_filename) {
+ lprintf(DEBUG, "Parameter file: %s\n", par_filename);
+ }
+ if (zip_filename) {
+ lprintf(DEBUG, "Zip file: %s\n", zip_filename);
+ }
+ if (img_filename) {
+ lprintf(DEBUG, "Image file: %s\n", img_filename);
+ }
+
+
+// open files from command line
+ // parameter/zip file
+ if (par_filename) {
+ f_par = fopen(par_filename, "rt");
+ if (!f_par) {
+ exitcode = errno;
+ printf("Input file %s: %s\n", par_filename, strerror(exitcode));
+ }
+ }
+
+ // image file
+ if (img_filename) {
+ f_img = fopen(img_filename, "wb");
+ if (!f_img) {
+ exitcode = errno;
+ printf("Output file %s: %s\n", img_filename, strerror(exitcode));
+ }
+ }
+
+ if (exitcode) {
+ return exitcode;
+ }
+
+
+// parameter file processing
+ if ((!exitcode) && (f_par)) {
+ lprintf(DEBUG, "parsing parameter file...\n");
+
+ exitcode = parse_par_file(f_par);
+
+ lprintf(DEBUG, "...done parsing file\n");
+ }
+ if (f_par) {
+ fclose(f_par);
+ }
+
+
+// check all input data
+ if ((!exitcode) && (par_filename)) {
+ lprintf(DEBUG, "checking mtd data...\n");
+
+ for (i = 1; i <= 4; i++) {
+ noupdate = 0;
+ sizecheck = 0;
+ magiccheck = 0;
+
+ switch (i) {
+ case 1:
+ mtd = &mtd_image;
+ sizecheck = ROOTFS_END_OFFSET;
+ magiccheck = 1;
+ break;
+ case 2:
+ mtd = &mtd_kernel;
+ sizecheck = mtd_kernel.size - 16;
+ magiccheck = 1;
+ break;
+ case 3:
+ mtd = &mtd_rootfs;
+ mtd->offset = mtd_kernel.size;
+ mtd->size = ROOTFS_END_OFFSET - mtd_kernel.size;
+ sizecheck = PRODUCT_ID_OFFSET - mtd_kernel.size;
+ magiccheck = 1;
+ break;
+ case 4:
+ mtd = &mtd_uboot;
+ mtd->offset = BOOT_ADDR_BASE_OFF;
+ noupdate = 1;
+ sizecheck = SN_OFF - BOOT_ADDR_BASE_OFF;
+ break;
+ default:
+ mtd = NULL;
+ exitcode = 1;
+ printf("unknown mtd check %i\n", i);
+ break;
+ }
+ if (!mtd) {
+ break;
+ }
+
+ lprintf(DEBUG_LVL2, " checking mtd %s\n", mtd->name);
+
+ // general checks
+
+ // no further checks if no file data present
+ if (!mtd->filename) {
+ continue;
+ }
+
+ // not updated by stock firmware
+ if (noupdate) {
+ printf("mtd %s is specified, but will not be updated as of Linksys firmware 2.0.19\n", mtd->name);
+ }
+
+ // general magic number check
+ magicerror = 0;
+ if (magiccheck) {
+ switch (i) {
+ case 1: // image
+ case 2: // kernel
+ if (!(
+ ((mtd->magic[0] == 0x27) && (mtd->magic[1] == 0x05)) // uImage
+ )) {
+ magicerror = 1;
+ }
+ break;
+ case 3: // rootfs
+ if (!(
+ ((mtd->magic[0] == 0x68) && (mtd->magic[1] == 0x73)) // squashfs
+ || ((mtd->magic[0] == 0x85) && (mtd->magic[1] == 0x19)) // jffs
+ )) {
+ magicerror = 1;
+ }
+ break;
+ default:
+ magicerror = 1;
+ break;
+ }
+ if (magicerror) {
+ printf("mtd %s input file %s has unknown magic number (0x%02X%02X)", mtd->name, mtd->filename, mtd->magic[0], mtd->magic[1]);
+ if (ignoremagic) {
+ printf("...ignoring");
+ } else {
+ exitcode = 1;
+ }
+ printf("\n");
+ }
+ }
+
+ // mtd specific size check
+ if (mtd == &mtd_image) {
+ if (mtd->filesize < 0x00200000) {
+ exitcode = 1;
+ printf("mtd %s input file %s too unrealistic small (0x%08lX)\n", mtd->name, mtd->filename, mtd->filesize);
+ }
+ }
+
+ if (mtd == &mtd_kernel) {
+ if (mtd->filesize < 0x00080000) {
+ exitcode = 1;
+ printf("mtd %s input file %s too unrealistic small (0x%08lX)\n", mtd->name, mtd->filename, mtd->filesize);
+ }
+ }
+
+ // general size check
+ if (sizecheck) {
+ if (sizecheck <= 0) {
+ exitcode = 1;
+ printf("mtd %s bad file size check (%i) due to input data\n", mtd->name, sizecheck);
+ } else {
+ if (mtd->filesize > sizecheck) {
+ exitcode = 1;
+ printf("mtd %s input file %s too big (0x%08lX)\n", mtd->name, mtd->filename, mtd->filesize);
+ }
+ }
+ }
+ }
+
+ // Check for mandatory parts
+ if ((!mtd_image.filename) && (!mtd_kernel.filename || !mtd_rootfs.filename)) {
+ exitcode = 1;
+ if (mtd_kernel.filename && !mtd_rootfs.filename) {
+ printf("Kernel without rootfs, either incorrectly specified or not at all in parameter file\n");
+ } else if (!mtd_kernel.filename && mtd_rootfs.filename) {
+ printf("Rootfs without kernel, either incorrectly specified or not at all in parameter file\n");
+ } else {
+ printf("Neither an image nor kernel with rootfs was/were correctly specified or at all in parameter file\n");
+ }
+ }
+
+ // Check for duplicate parts
+ if ((mtd_image.filename) && (mtd_kernel.filename || mtd_rootfs.filename)) {
+ exitcode = 1;
+ printf("Image and kernel/rootfs specified in parameter file\n");
+ }
+
+ lprintf(DEBUG, "...done checking mtd data\n");
+ }
+
+
+// bin creation in memory
+ if ((!exitcode) && (par_filename)) {
+ bin_filename = "wrt350n.bin";
+
+ lprintf(DEBUG, "creating bin file %s...\n", bin_filename);
+
+ exitcode = create_bin_file(bin_filename);
+
+ lprintf(DEBUG, "...done creating bin file\n");
+ }
+
+// zip file creation
+ if ((!exitcode) && (!onlybin) && (!zip_filename)) {
+ zip_filename = "wrt350n.zip";
+
+ lprintf(DEBUG, "creating zip file %s...\n", zip_filename);
+
+ exitcode = create_zip_file(zip_filename, bin_filename);
+
+ lprintf(DEBUG, "...done creating zip file\n");
+ }
+
+
+// img file creation
+ if ((!exitcode) && (f_img)) {
+ lprintf(DEBUG, "creating img file...\n");
+
+ exitcode = create_img_file(f_img, img_filename, zip_filename);
+
+ lprintf(DEBUG, "...done creating img file\n");
+ }
+
+// clean up
+ if (f_img) {
+ fclose(f_img);
+ }
+
+// end program
+ return exitcode;
+}
diff --git a/tools/xz/Makefile b/tools/xz/Makefile
new file mode 100644
index 0000000..ce67acf
--- /dev/null
+++ b/tools/xz/Makefile
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2006-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=xz
+PKG_VERSION:=5.2.2
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://tukaani.org/xz \
+ http://fossies.org/linux/misc
+PKG_MD5SUM:=f90c9a0c8b259aee2234c4e0d7fd70af
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+
+HOST_CONFIGURE_ARGS += \
+ --enable-static=yes \
+ --enable-shared=no \
+
+define Host/Install
+ +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR) install xzlinks="unxz xzcat"
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/xz/patches/100-freebsd-compat.patch b/tools/xz/patches/100-freebsd-compat.patch
new file mode 100644
index 0000000..480a652
--- /dev/null
+++ b/tools/xz/patches/100-freebsd-compat.patch
@@ -0,0 +1,11 @@
+--- a/src/common/tuklib_integer.h
++++ b/src/common/tuklib_integer.h
+@@ -48,7 +48,7 @@
+ // Operating system specific features //
+ ////////////////////////////////////////
+
+-#if defined(HAVE_BYTESWAP_H)
++#if defined(HAVE_BYTESWAP_H) && !defined(__FreeBSD__)
+ // glibc, uClibc, dietlibc
+ # include <byteswap.h>
+ # ifdef HAVE_BSWAP_16
diff --git a/tools/yaffs2/Makefile b/tools/yaffs2/Makefile
new file mode 100644
index 0000000..bc98a6c
--- /dev/null
+++ b/tools/yaffs2/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2008-2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=yaffs2_android
+PKG_VERSION:=2008-12-18
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://android.googlesource.com/platform/external/yaffs2
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)
+PKG_SOURCE_VERSION:=d333fc232d7e5ae3370080d5d6f7d88ea9c6b3a1
+PKG_MIRROR_MD5SUM:=8145d4dd9b46face26121f27ad60cc1c
+HOST_BUILD_DIR=$(BUILD_DIR_HOST)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/host-build.mk
+
+define Host/Compile
+ $(MAKE) -C $(HOST_BUILD_DIR)/yaffs2/utils \
+ CC="$(HOSTCC)" \
+ CFLAGS="$(HOST_CFLAGS) -include endian.h" \
+ mkyaffs2image
+endef
+
+define Host/Install
+ $(INSTALL_DIR) $(STAGING_DIR_HOST)/bin
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/yaffs2/utils/mkyaffs2image $(STAGING_DIR_HOST)/bin/
+endef
+
+define Host/Clean
+ rm -f $(STAGING_DIR_HOST)/bin/mkyaffs2image
+endef
+
+$(eval $(call HostBuild))
diff --git a/tools/yaffs2/patches/100-compile.patch b/tools/yaffs2/patches/100-compile.patch
new file mode 100644
index 0000000..2f83e1f
--- /dev/null
+++ b/tools/yaffs2/patches/100-compile.patch
@@ -0,0 +1,125 @@
+--- a/yaffs2/utils/Makefile
++++ b/yaffs2/utils/Makefile
+@@ -16,12 +16,11 @@
+
+ #KERNELDIR = /usr/src/kernel-headers-2.4.18
+
+-CFLAGS = -I/usr/include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL
+-CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
+-CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
++CPPFLAGS = -I.. -DCONFIG_YAFFS_UTIL
++CFLAGS = -O2
+
+ ## Change if you are using a cross-compiler
+-MAKETOOLS =
++MAKETOOLS =
+
+ CC=$(MAKETOOLS)gcc
+
+@@ -41,7 +40,7 @@ $(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS
+ ln -s ../$@ $@
+
+ $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) : %.o: %.c
+- $(CC) -c $(CFLAGS) $< -o $@
++ $(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+ mkyaffsimage: $(COMMONOBJS) $(MKYAFFSIMAGEOBJS)
+ $(CC) -o $@ $(COMMONOBJS) $(MKYAFFSIMAGEOBJS)
+--- a/yaffs2/utils/mkyaffs2image.c
++++ b/yaffs2/utils/mkyaffs2image.c
+@@ -32,8 +32,6 @@
+ #include <string.h>
+ #include <unistd.h>
+
+-#include <private/android_filesystem_config.h>
+-
+ #include "yaffs_ecc.h"
+ #include "yaffs_guts.h"
+
+@@ -69,10 +67,12 @@ static int outFile;
+
+ static int error;
+
+-#ifdef HAVE_BIG_ENDIAN
++#if BYTE_ORDER == BIG_ENDIAN
+ static int convert_endian = 1;
+-#elif defined(HAVE_LITTLE_ENDIAN)
++#elif BYTE_ORDER == LITTLE_ENDIAN
+ static int convert_endian = 0;
++#else
++#error Unknown endian type
+ #endif
+
+ static int obj_compare(const void *a, const void * b)
+@@ -298,8 +298,8 @@ static int write_object_header(int objId
+
+ static void fix_stat(const char *path, struct stat *s)
+ {
+- path += source_path_len;
+- fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode);
++ s->st_uid = 0;
++ s->st_gid = 0;
+ }
+
+ static int process_directory(int parent, const char *path, int fixstats)
+@@ -342,9 +342,8 @@ static int process_directory(int parent,
+ newObj = obj_id++;
+ nObjects++;
+
+- if (fixstats) {
++ if (fixstats)
+ fix_stat(full_name, &stats);
+- }
+
+ //printf("Object %d, %s is a ",newObj,full_name);
+
+@@ -473,13 +472,13 @@ int main(int argc, char *argv[])
+ fprintf(stderr," -f fix file stat (mods, user, group) for device\n");
+ fprintf(stderr," dir the directory tree to be converted\n");
+ fprintf(stderr," image_file the output file to hold the image\n");
+- fprintf(stderr," 'convert' produce a big-endian image from a little-endian machine\n");
++ fprintf(stderr," 'convert' produce a big-endian image\n");
+ exit(1);
+ }
+
+ if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
+ {
+- convert_endian = 1;
++ convert_endian = !convert_endian;
+ }
+
+ if(stat(argv[1],&stats) < 0)
+@@ -503,20 +502,9 @@ int main(int argc, char *argv[])
+ exit(1);
+ }
+
+- if (fixstats) {
+- int len = strlen(argv[1]);
+-
+- if((len >= 4) && (!strcmp(argv[1] + len - 4, "data"))) {
+- source_path_len = len - 4;
+- } else if((len >= 7) && (!strcmp(argv[1] + len - 6, "system"))) {
+- source_path_len = len - 6;
+- } else {
+- fprintf(stderr,"Fixstats (-f) option requested but filesystem is not data or android!\n");
+- exit(1);
+- }
++ if (fixstats)
+ fix_stat(argv[1], &stats);
+- }
+-
++
+ //printf("Processing directory %s into image file %s\n",argv[1],argv[2]);
+ error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL);
+ if(error)
+--- a/yaffs2/devextras.h
++++ b/yaffs2/devextras.h
+@@ -37,7 +37,7 @@ typedef unsigned char __u8;
+ typedef unsigned short __u16;
+ typedef unsigned __u32;
+
+-#if defined(__APPLE__)
++#if defined(__APPLE__) || defined(__FreeBSD__)
+ typedef long long loff_t;
+ #endif
+
diff --git a/tools/yaffs2/patches/110-openbsd-compat.patch b/tools/yaffs2/patches/110-openbsd-compat.patch
new file mode 100644
index 0000000..cfafc1c
--- /dev/null
+++ b/tools/yaffs2/patches/110-openbsd-compat.patch
@@ -0,0 +1,14 @@
+diff -Nur yaffs2_android.orig/yaffs2/yaffs_guts.h yaffs2_android/yaffs2/yaffs_guts.h
+--- yaffs2_android.orig/yaffs2/yaffs_guts.h Sun Feb 15 16:23:50 2009
++++ yaffs2_android/yaffs2/yaffs_guts.h Tue Mar 5 15:45:21 2013
+@@ -823,6 +823,10 @@
+ int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr);
+ int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr);
+
++#if defined(__OpenBSD__)
++#define loff_t off_t
++#endif
++
+ /* File operations */
+ int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
+ int nBytes);