Initial commit

This commit is contained in:
domenico
2025-06-24 15:51:28 +02:00
commit 22031d9dab
6862 changed files with 1462554 additions and 0 deletions

152
tools/Makefile Normal file
View File

@@ -0,0 +1,152 @@
#
# 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
ifdef CONFIG_GCC_USE_GRAPHITE
BUILD_ISL = y
endif
endif
ifneq ($(CONFIG_SDK)$(CONFIG_PACKAGE_kmod-b43)$(CONFIG_PACKAGE_b43legacy-firmware)$(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 mklibs zlib
tools-y += sstrip make-ext4fs e2fsprogs mtd-utils mkimage
tools-y += firmware-utils patch-image quilt padjffs2
tools-y += mm-macros missing-macros cmake scons bc findutils gengetopt patchelf
tools-y += mtools dosfstools libressl
tools-$(CONFIG_TARGET_orion_generic) += wrt350nv2-builder upslug2
tools-$(CONFIG_TARGET_x86) += qemu
tools-$(CONFIG_TARGET_mxs) += elftosb sdimage
tools-$(CONFIG_TARGET_ar71xx) += lzma-old squashfs
tools-$(CONFIG_USES_MINOR) += kernel2minor
tools-y += lzma squashfs4
tools-$(BUILD_B43_TOOLS) += b43-tools
tools-$(BUILD_ISL) += isl
tools-$(CONFIG_USE_SPARSE) += sparse
tools-$(CONFIG_TARGET_apm821xx) += genext2fs
# builddir dependencies
$(curdir)/bison/compile := $(curdir)/flex/compile
$(curdir)/flex/compile := $(curdir)/libtool/compile
$(curdir)/libtool/compile := $(curdir)/m4/compile $(curdir)/autoconf/compile $(curdir)/automake/compile $(curdir)/missing-macros/compile
$(curdir)/squashfs/compile := $(curdir)/lzma-old/compile
$(curdir)/squashfs4/compile := $(curdir)/xz/compile $(curdir)/zlib/compile
$(curdir)/quilt/compile := $(curdir)/autoconf/compile $(curdir)/findutils/compile
$(curdir)/autoconf/compile := $(curdir)/m4/compile
$(curdir)/automake/compile := $(curdir)/m4/compile $(curdir)/autoconf/compile $(curdir)/pkg-config/compile $(curdir)/xz/compile
$(curdir)/gmp/compile := $(curdir)/libtool/compile
$(curdir)/mpc/compile := $(curdir)/mpfr/compile $(curdir)/gmp/compile
$(curdir)/mpfr/compile := $(curdir)/gmp/compile
$(curdir)/mtd-utils/compile := $(curdir)/libtool/compile $(curdir)/e2fsprogs/compile $(curdir)/zlib/compile
$(curdir)/mklibs/compile := $(curdir)/libtool/compile
$(curdir)/qemu/compile := $(curdir)/e2fsprogs/compile $(curdir)/zlib/compile
$(curdir)/upslug2/compile := $(curdir)/libtool/compile
$(curdir)/mm-macros/compile := $(curdir)/libtool/compile
$(curdir)/missing-macros/compile := $(curdir)/autoconf/compile
$(curdir)/e2fsprogs/compile := $(curdir)/libtool/compile
$(curdir)/libelf/compile := $(curdir)/libtool/compile
$(curdir)/sdcc/compile := $(curdir)/bison/compile
$(curdir)/b43-tools/compile := $(curdir)/bison/compile
$(curdir)/padjffs2/compile := $(curdir)/findutils/compile
$(curdir)/isl/compile := $(curdir)/gmp/compile
$(curdir)/bc/compile := $(curdir)/bison/compile
$(curdir)/findutils/compile := $(curdir)/bison/compile
$(curdir)/gengetopt/compile := $(curdir)/libtool/compile
$(curdir)/patchelf/compile := $(curdir)/libtool/compile
$(curdir)/dosfstools/compile := $(curdir)/autoconf/compile $(curdir)/automake/compile
$(curdir)/libressl/compile := $(curdir)/pkg-config/compile
$(curdir)/mkimage/compile += $(curdir)/libressl/compile
$(curdir)/firmware-utils/compile += $(curdir)/libressl/compile $(curdir)/zlib/compile
$(curdir)/cmake/compile += $(curdir)/libressl/compile
$(curdir)/zlib/compile := $(curdir)/cmake/compile
$(curdir)/wrt350nv2-builder/compile := $(curdir)/zlib/compile
$(curdir)/lzma-old/compile := $(curdir)/zlib/compile
$(curdir)/make-ext4fs/compile := $(curdir)/zlib/compile
ifneq ($(HOST_OS),Linux)
tools-y += coreutils
endif
ifneq ($(CONFIG_CCACHE)$(CONFIG_SDK),)
$(foreach tool, $(filter-out xz patch,$(tools-y)), $(eval $(curdir)/$(tool)/compile += $(curdir)/ccache/compile))
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/compile)))
$(foreach tool, $(filter-out xz,$(tools-y)), $(eval $(curdir)/$(tool)/compile += $(curdir)/xz/compile))
# make any tool depend on tar, xz and patch to ensure that archives can be unpacked and patched properly
tools-core := tar xz patch
$(foreach tool, $(tools-y), $(eval $(curdir)/$(tool)/compile += $(patsubst %,$(curdir)/%/compile,$(tools-core))))
tools-y += $(tools-core)
# make core tools depend on sed and flock
$(foreach tool, $(tools-core), $(eval $(curdir)/$(tool)/compile += $(curdir)/sed/compile))
$(curdir)/sed/compile := $(curdir)/flock/compile
tools-y += flock sed
$(curdir)/autoremove := 1
$(curdir)/builddirs := $(tools-y) $(tools-dep) $(tools-)
$(curdir)/builddirs-default := $(tools-y)
ifdef CHECK_ALL
$(curdir)/builddirs-check:=$($(curdir)/builddirs)
$(curdir)/builddirs-download:=$($(curdir)/builddirs)
endif
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: $(curdir)/compile
tools_enabled = $(foreach tool,$(sort $(tools-y) $(tools-)),$(if $(filter $(tool),$(tools-y)),y,n))
$(eval $(call stampfile,$(curdir),tools,compile,,_$(subst $(space),,$(tools_enabled))))
$(eval $(call stampfile,$(curdir),tools,check,$(TMP_DIR)/.build))
$(eval $(call subdir,$(curdir)))

37
tools/autoconf/Makefile Normal file
View File

@@ -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_HASH:=64ebcec9f8ac5b2487125a86a7760d2591ac9e1d3dbd59489633f9de62a57684
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))

View File

@@ -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

View File

@@ -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 \

View File

@@ -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* \

51
tools/automake/Makefile Normal file
View File

@@ -0,0 +1,51 @@
#
# 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_CPE_ID:=cpe:/a:gnu:automake
PKG_VERSION:=1.15.1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@GNU/automake
PKG_HASH:=af6ba39142220687c500f79b4aa2f181d9b24e4f8d8ec497cea4ba26c64bedaf
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)
$(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))

2
tools/automake/files/aclocal Executable file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env sh
aclocal.real $ACLOCAL_INCLUDE $@

View File

@@ -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-2017 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-2017 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-2017 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-2017 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify

View File

@@ -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?

View File

@@ -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)'

50
tools/b43-tools/Makefile Normal file
View File

@@ -0,0 +1,50 @@
#
# 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_URL:=https://github.com/mbuesch/b43-tools.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE_VERSION:=8dce53297966b31b6c70a7a03c2433978dd9f288
PKG_MIRROR_HASH:=247eb0297f14fbcc828685cc353150f30fa03bf886e7a477aadc4161d9c0458d
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))

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

21
tools/bc/Makefile Normal file
View File

@@ -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_HASH:=7ee4abbcfac03d8a6e1a8a3440558a3d239d6b858585063e745c760957725ecc
include $(INCLUDE_DIR)/host-build.mk
$(eval $(call HostBuild))

View File

@@ -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

30
tools/bison/Makefile Normal file
View File

@@ -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.5
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
PKG_HASH:=075cef2e814642e30e10e8155e93022e4a91ca38a65aa1d5467d4e969f97f338
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))

View File

@@ -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");

View File

@@ -0,0 +1,19 @@
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index ff7c9c8..f391832 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -739,14 +739,6 @@ _GL_WARN_ON_USE (getline, "getline is unportable - "
# 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 && !defined __cplusplus
-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
-#endif
-
#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
struct obstack;
/* Grow an obstack with formatted output. Return the number of

2
tools/bison/scripts/yacc Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec bison -y "$@"

36
tools/ccache/Makefile Normal file
View File

@@ -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
include $(INCLUDE_DIR)/target.mk
PKG_NAME:=ccache
PKG_VERSION:=3.5
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://download.samba.org/pub/ccache/ \
https://samba.org/ftp/ccache/
PKG_HASH:=bdd44b72ae4506a2e2deef9fefb15c606a474bbca7658cd2be26105155eec012
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))

2
tools/ccache/files/ccache_cc Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec ccache "${TARGET_CC_NOCACHE}" "$@"

2
tools/ccache/files/ccache_cxx Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec ccache "${TARGET_CXX_NOCACHE}" "$@"

View File

@@ -0,0 +1,10 @@
--- a/src/ccache.c
+++ b/src/ccache.c
@@ -1940,6 +1940,7 @@ calculate_object_hash(struct args *args,
"CPLUS_INCLUDE_PATH",
"OBJC_INCLUDE_PATH",
"OBJCPLUS_INCLUDE_PATH", // clang
+ "GCC_HONOUR_COPTS",
NULL
};
for (const char **p = envvars; *p; ++p) {

36
tools/cmake/Makefile Normal file
View File

@@ -0,0 +1,36 @@
#
# Copyright (C) 2006-2016 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.11.4
PKG_RELEASE:=2
PKG_CPE_ID:=cpe:/a:kitware:cmake
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://cmake.org/files/v3.11/ \
https://fossies.org/linux/misc/
PKG_HASH:=8f864e9f78917de3e1483e256270daabc4a321741592c5b36af028e72bff87f5
HOST_BUILD_PARALLEL:=1
HOST_CONFIGURE_PARALLEL:=1
include $(INCLUDE_DIR)/host-build.mk
HOST_CONFIGURE_VARS += \
MAKEFLAGS="$(HOST_JOBS)" \
CXXFLAGS="$(HOST_CFLAGS)"
HOST_CONFIGURE_ARGS := \
$(if $(MAKE_JOBSERVER),--parallel="$(MAKE_JOBSERVER)") \
--prefix=$(STAGING_DIR_HOST)
ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
HOST_MAKE_FLAGS += VERBOSE=1
endif
$(eval $(call HostBuild))

View File

@@ -0,0 +1,34 @@
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -284,15 +284,6 @@ add_RunCMake_test(no_install_prefix)
add_RunCMake_test(configure_file)
add_RunCMake_test(CTestTimeoutAfterMatch)
-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
@@ -422,13 +422,6 @@ if(BUILD_TESTING)
list(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
- if(NOT DEFINED CMake_TEST_Qt4)
- set(CMake_TEST_Qt4 1)
- endif()
- if(CMake_TEST_Qt4 AND NOT QT4_FOUND)
- find_package(Qt4 QUIET)
- endif()
-
if(CMake_TEST_Qt4 AND 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"

View File

@@ -0,0 +1,11 @@
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
@@ -28,7 +28,7 @@
#include <openssl/evp.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline EVP_MD_CTX *EVP_MD_CTX_new(void)

View File

@@ -0,0 +1,37 @@
From: Jo-Philipp Wich <jo@mein.io>
Date: Wed, 11 Jan 2017 03:36:04 +0100
Subject: [PATCH] cmcurl: link librt
When cmake is linked against LibreSSL, there might be an indirect
dependency on librt on certain systems if LibreSSL's libcrypto uses
clock_gettime() from librt:
[ 28%] Linking C executable LIBCURL
.../lib/libcrypto.a(getentropy_linux.o): In function `getentropy_fallback':
getentropy_linux.c:(.text+0x16d): undefined reference to `clock_gettime'
getentropy_linux.c:(.text+0x412): undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
make[5]: *** [Utilities/cmcurl/LIBCURL] Error 1
Modify the cmcurl CMakeLists.txt to check for clock_gettime() in librt
and unconditionally link the rt library when the symbol is found.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
---
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -461,6 +461,14 @@ if(CMAKE_USE_OPENSSL)
set(USE_OPENSSL ON)
set(HAVE_LIBCRYPTO ON)
set(HAVE_LIBSSL ON)
+ check_library_exists("rt" clock_gettime "" HAVE_LIBRT)
+ if(HAVE_LIBRT)
+ list(APPEND OPENSSL_LIBRARIES rt)
+ endif()
+ check_library_exists("pthread" pthread_once "" HAVE_PTHREAD)
+ if(HAVE_PTHREAD)
+ list(APPEND OPENSSL_LIBRARIES pthread)
+ endif()
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
include_directories(${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})

View File

@@ -0,0 +1,14 @@
--- a/bootstrap
+++ b/bootstrap
@@ -1151,7 +1151,10 @@ int main(){ printf("1%c", (char)0x0a); r
' > "test.c"
cmake_original_make_flags="${cmake_make_flags}"
if [ "x${cmake_parallel_make}" != "x" ]; then
- cmake_make_flags="${cmake_make_flags} -j ${cmake_parallel_make}"
+ case "$cmake_parallel_make" in
+ [0-9]*) cmake_parallel_make="-j ${cmake_parallel_make}";;
+ esac
+ cmake_make_flags="${cmake_make_flags} ${cmake_parallel_make}"
fi
for a in ${cmake_make_processors}; do
if [ -z "${cmake_make_processor}" ] && cmake_try_make "${a}" "${cmake_make_flags}" >> ../cmake_bootstrap.log 2>&1; then

View File

@@ -0,0 +1,68 @@
From 7c90c93c0b061da81f69fabdd57125b2783c15fb Mon Sep 17 00:00:00 2001
From: Bernard Spil <brnrd@FreeBSD.org>
Date: Mon, 2 Apr 2018 19:04:06 +0200
Subject: [PATCH] openssl: fix build with LibreSSL 2.7
- LibreSSL 2.7 implements (most of) OpenSSL 1.1 API
Fixes #2319
Closes #2447
Closes #2448
Signed-off-by: Bernard Spil <brnrd@FreeBSD.org>
---
lib/vtls/openssl.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -104,7 +104,8 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */
#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */
@@ -128,7 +129,8 @@ static unsigned long OpenSSL_version_num
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define HAVE_X509_GET0_SIGNATURE 1
#endif
@@ -147,7 +149,7 @@ static unsigned long OpenSSL_version_num
* Whether SSL_CTX_set_keylog_callback is available.
* OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
* BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
+ * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it
* lies and pretends to be OpenSSL 2.0.0).
*/
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
@@ -259,7 +261,9 @@ static void tap_ssl_key(const SSL *ssl,
if(!session || !keylog_file_fp)
return;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
/* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
* we have a valid SSL context if we have a non-NULL session. */
SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
@@ -2082,8 +2086,7 @@ static CURLcode ossl_connect_step1(struc
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
/* it will be handled later with the context options */
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
req_method = TLS_client_method();
#else
req_method = SSLv23_client_method();

View File

@@ -0,0 +1,37 @@
From 5da00ad75b09e262774ec3675bbe4d5a4502a852 Mon Sep 17 00:00:00 2001
From: Bernard Spil <brnrd@FreeBSD.org>
Date: Sun, 1 Apr 2018 23:01:44 +0200
Subject: [PATCH] fix build with LibreSSL 2.7
LibreSSL 2.7 adds OpenSSL 1.1 API leading to conflicts on method names
See also: https://bugs.freebsd.org/226853
Signed-off-by: Bernard Spil <brnrd@FreeBSD.org>
---
libarchive/archive_openssl_hmac_private.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
@@ -28,7 +28,8 @@
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline HMAC_CTX *HMAC_CTX_new(void)
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
@@ -28,7 +28,8 @@
#include <openssl/evp.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline EVP_MD_CTX *EVP_MD_CTX_new(void)

37
tools/coreutils/Makefile Normal file
View File

@@ -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:=coreutils
PKG_CPE_ID:=cpe:/a:gnu:coreutils
PKG_VERSION:=8.27
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@GNU/coreutils
PKG_HASH:=8891d349ee87b9ff7870f52b6d9312a9db672d2439d289bc57084771ca21656b
HOST_BUILD_PARALLEL := 1
BUILD_PROGRAMS = date readlink
include $(INCLUDE_DIR)/host-build.mk
BUILD_BINS = $(patsubst %,src/%,$(BUILD_PROGRAMS))
HOST_CONFIGURE_ARGS += \
--enable-install-program=$(subst $(space),$(comma),$(strip $(BUILD_PROGRAMS)))
HOST_MAKE_FLAGS += \
PROGRAMS="$(BUILD_BINS)" \
LIBRARIES= MANS= SUBDIRS=.
define Host/Install
$(INSTALL_DIR) $(1)/bin
$(CP) $(patsubst %,$(HOST_BUILD_DIR)/%,$(BUILD_BINS)) $(1)/bin/
endef
$(eval $(call HostBuild))

View File

@@ -0,0 +1,25 @@
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -4858,7 +4858,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *
#endif
*fbp = dp->conversion;
#if USE_SNPRINTF
-# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+# if ! (((__GLIBC__ > 2 \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \
+ && !defined __UCLIBC__) \
+ || (defined __APPLE__ && defined __MACH__) \
+ || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
fbp[1] = '%';
fbp[2] = 'n';
fbp[3] = '\0';
@@ -4872,6 +4876,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *
in format strings in writable memory may crash the program
(if compiled with _FORTIFY_SOURCE=2), so we should avoid it
in this situation. */
+ /* macOS 10.13 High Sierra behaves like glibc with
+ _FORTIFY_SOURCE=2, and older macOS releases
+ presumably do not need %n. */
/* On native Windows systems (such as mingw), we can avoid using
%n because:
- Although the gl_SNPRINTF_TRUNCATION_C99 test fails,

27
tools/dosfstools/Makefile Normal file
View File

@@ -0,0 +1,27 @@
#
# Copyright (C) 2012-2015 OpenWrt.org
# Copyright (C) 2016 LEDE-Project.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_CPE_ID:=cpe:/a:dosfstools_project:dosfstools
PKG_VERSION:=4.1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/dosfstools/dosfstools/releases/download/v$(PKG_VERSION)/ \
http://fossies.org/linux/misc
PKG_HASH:=e6b2aca70ccc3fe3687365009dd94a2e18e82b688ed4e260e04b7412471cc173
HOST_FIXUP:=autoreconf
include $(INCLUDE_DIR)/host-build.mk
ifeq ($(HOST_OS),Darwin)
HOST_CFLAGS += -UHAVE_ENDIAN_H
endif
$(eval $(call HostBuild))

View File

@@ -0,0 +1,27 @@
From 1c6c135ee15e449c1bf2e76d5307f83a3a1d7425 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
Date: Tue, 11 Oct 2016 12:07:48 +0200
Subject: [PATCH] Switch to AC_CHECK_LIB for iconv library linking.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
AC_SEARCH_LIB doesn't work properly for openwrt/lede when building dosfstools
as a package.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/configure.ac
+++ b/configure.ac
@@ -59,7 +59,7 @@ if test "x$with_udev" != "xno"; then
[true])
fi
-AC_SEARCH_LIBS(iconv_open, iconv)
+AC_CHECK_LIB(iconv, iconv_open)
# xxd (distributed with vim) is used in the testsuite
AC_CHECK_PROG([XXD_FOUND], [xxd], [yes])

50
tools/e2fsprogs/Makefile Normal file
View File

@@ -0,0 +1,50 @@
#
# 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:=e2fsprogs
PKG_CPE_ID:=cpe:/a:e2fsprogs_project:e2fsprogs
PKG_VERSION:=1.44.2
PKG_HASH:=8324cf0b6e81805a741d94087b00e99f7e16144f1ee5a413709a1fa6948b126c
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/linux/kernel/people/tytso/e2fsprogs/v$(PKG_VERSION)/
HOST_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/host-build.mk
HOST_CFLAGS += $(FPIC)
HOST_CONFIGURE_ARGS += \
--disable-elf-shlibs \
--enable-libuuid \
--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))

View File

@@ -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 */

View File

@@ -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
@LINUX_CMT@E4CRYPT_PROG = e4crypt

View File

@@ -0,0 +1,12 @@
--- a/lib/blkid/getsize.c
+++ b/lib/blkid/getsize.c
@@ -29,6 +29,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>

View File

@@ -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>
+
#ifndef HAVE___U8
#define HAVE___U8
#ifdef __U8_TYPEDEF
--- a/lib/ext2fs/ext2_types.h.in
+++ b/lib/ext2fs/ext2_types.h.in
@@ -9,6 +9,8 @@
@ASM_TYPES_HEADER@
+#include <stdint.h>
+
#ifndef HAVE___U8
#define HAVE___U8
#ifdef __U8_TYPEDEF

26
tools/elftosb/Makefile Normal file
View File

@@ -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_HASH:=77bb6981620f7575b87d136d94c7daa88dd09195959cc75fc18b138369ecd42b
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))

View File

@@ -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")

View File

@@ -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;

View File

@@ -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")

29
tools/expat/Makefile Normal file
View File

@@ -0,0 +1,29 @@
#
# 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_CPE_ID:=cpe:/a:libexpat:expat
PKG_VERSION:=2.2.9
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_HASH:=f1063084dc4302a427dabcca499c8312b3a32a29b7d2506653ecc8f950a9a237
PKG_SOURCE_URL:=@SF/expat
HOST_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/host-build.mk
HOST_CONFIGURE_ARGS += \
--without-docbook
define Host/Install
$(MAKE) -C $(HOST_BUILD_DIR) install
endef
$(eval $(call HostBuild))

21
tools/findutils/Makefile Normal file
View File

@@ -0,0 +1,21 @@
#
# Copyright (C) 2006-2016 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_CPE_ID:=cpe:/a:gnu:findutils
PKG_VERSION:=4.6.0
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
PKG_HASH:=ded4c9f73731cd48fec3b6bdaccce896473b6d8e337e9612e16cf1431bb1169d
HOST_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/host-build.mk
$(eval $(call HostBuild))

View File

@@ -0,0 +1,13 @@
--- a/gl/lib/mountlist.c
+++ b/gl/lib/mountlist.c
@@ -17,6 +17,10 @@
#include <config.h>
+#ifdef MAJOR_IN_SYSMACROS
+# include <sys/sysmacros.h>
+#endif
+
#include "mountlist.h"
#include <limits.h>

View File

@@ -0,0 +1,104 @@
Subject: Workaround change in glibc
Temporary workaround to compile with glibc 2.28, which
deprecated some constants
Based on the workaround made for the tools/m4 package
--- a/gl/lib/stdio-impl.h
+++ b/gl/lib/stdio-impl.h
@@ -18,6 +18,12 @@
the same implementation of stdio extension API, except that some fields
have different naming conventions, or their access requires some casts. */
+/* Glibc 2.28 made _IO_IN_BACKUP private. For now, work around this
+ problem by defining it ourselves. FIXME: Do not rely on glibc
+ internals. */
+#if !defined _IO_IN_BACKUP && defined _IO_EOF_SEEN
+# define _IO_IN_BACKUP 0x100
+#endif
/* BSD stdio derived implementations. */
--- a/gl/lib/freadahead.c
+++ b/gl/lib/freadahead.c
@@ -25,7 +25,7 @@
size_t
freadahead (FILE *fp)
{
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
if (fp->_IO_write_ptr > fp->_IO_write_base)
return 0;
return (fp->_IO_read_end - fp->_IO_read_ptr)
--- a/gl/lib/fseeko.c
+++ b/gl/lib/fseeko.c
@@ -47,7 +47,7 @@ fseeko (FILE *fp, off_t offset, int when
#endif
/* These tests are based on fpurge.c. */
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
if (fp->_IO_read_end == fp->_IO_read_ptr
&& fp->_IO_write_ptr == fp->_IO_write_base
&& fp->_IO_save_base == NULL)
@@ -123,7 +123,7 @@ fseeko (FILE *fp, off_t offset, int when
return -1;
}
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
fp->_flags &= ~_IO_EOF_SEEN;
fp->_offset = pos;
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
--- a/gl/lib/fflush.c
+++ b/gl/lib/fflush.c
@@ -33,7 +33,7 @@
#undef fflush
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
/* Clear the stream's ungetc buffer, preserving the value of ftello (fp). */
static void
@@ -72,7 +72,7 @@ clear_ungetc_buffer (FILE *fp)
#endif
-#if ! (defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */)
+#if ! (defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */)
# if (defined __sferror || defined __DragonFly__ || defined __ANDROID__) && defined __SNPT
/* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
@@ -148,7 +148,7 @@ rpl_fflush (FILE *stream)
if (stream == NULL || ! freading (stream))
return fflush (stream);
-#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+#if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
clear_ungetc_buffer_preserving_position (stream);
--- a/gl/lib/freading.c
+++ b/gl/lib/freading.c
@@ -31,7 +31,7 @@ freading (FILE *fp)
/* Most systems provide FILE as a struct and the necessary bitmask in
<stdio.h>, because they need it for implementing getc() and putc() as
fast macros. */
-# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+# if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
return ((fp->_flags & _IO_NO_WRITES) != 0
|| ((fp->_flags & (_IO_NO_READS | _IO_CURRENTLY_PUTTING)) == 0
&& fp->_IO_read_base != NULL));
--- a/gl/lib/fpurge.c
+++ b/gl/lib/fpurge.c
@@ -62,7 +62,7 @@ fpurge (FILE *fp)
/* Most systems provide FILE as a struct and the necessary bitmask in
<stdio.h>, because they need it for implementing getc() and putc() as
fast macros. */
-# if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
+# if defined _IO_EOF_SEEN || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
fp->_IO_read_end = fp->_IO_read_ptr;
fp->_IO_write_ptr = fp->_IO_write_base;
/* Avoid memory leak when there is an active ungetc buffer. */

View File

@@ -0,0 +1,93 @@
#
# 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,otrx)
$(call cc,motorola-bin)
$(call cc,dgfirmware)
$(call cc,mksenaofw md5)
$(call cc,trx2usr)
$(call cc,ptgen)
$(call cc,srec2bin)
$(call cc,mkmylofw)
$(call cc,mkcsysimg)
$(call cc,mkzynfw)
$(call cc,lzma2eva,-lz)
$(call cc,mkcasfw)
$(call cc,mkfwimage,-lz -Wall)
$(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 mktplinkfw-lib md5, -Wall -fgnu89-inline)
$(call cc,mktplinkfw2 mktplinkfw-lib md5, -fgnu89-inline)
$(call cc,tplink-safeloader md5, -Wall --std=gnu99)
$(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,mkwrggimg md5, -Wall)
$(call cc,mkedimaximg)
$(call cc,mkbrncmdline)
$(call cc,mkbrnimg)
$(call cc,mkdapimg)
$(call cc,mkdapimg2)
$(call cc, mkcameofw, -Wall)
$(call cc,seama md5)
$(call cc,oseama md5, -Wall)
$(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, -Wall)
$(call cc,edimax_fw_header, -Wall)
$(call cc,mkmerakifw sha1, -Wall)
$(call cc,mkmerakifw-old, -Wall)
$(call cc,jcgimage, -lz -Wall)
$(call cc,mkbuffaloimg, -Wall)
$(call cc,zyimage, -Wall)
$(call cc,mkdhpimg buffalo-lib, -Wall)
$(call cc,mkdlinkfw mkdlinkfw-lib, -lz -Wall --std=gnu99)
$(call cc,dns313-header, -Wall)
endef
define Host/Install
$(INSTALL_BIN) $(HOST_BUILD_DIR)/bin/* $(STAGING_DIR_HOST)/bin/
endef
$(eval $(call HostBuild))

View File

@@ -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;
}

View File

@@ -0,0 +1,358 @@
/*
* 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 <errno.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 = "E2100L",
.pattern = "NL1X",
.hw_ver = 0x00,
.sn = 0x0f,
.flags = {0x3f, 0x00},
},
{
.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);
}
static time_t source_date_epoch = -1;
static void set_source_date_epoch() {
char *env = getenv("SOURCE_DATE_EPOCH");
char *endptr = env;
errno = 0;
if (env && *env) {
source_date_epoch = strtoull(env, &endptr, 10);
if (errno || (endptr && *endptr != '\0')) {
fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
exit(1);
}
}
}
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();
}
set_source_date_epoch();
if (source_date_epoch != -1) {
t = source_date_epoch;
} else 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;
}

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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" );
}

View File

@@ -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 );

View File

@@ -0,0 +1,322 @@
/*
* 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;
static int size;
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"
" -S Size of unencrypted data in file (encryption)\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, tail_dst, tail_len, tail_src;
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;
}
if (size) {
tail_dst = enc_compute_buf_len(product, version, size);
tail_len = src_len - size;
totlen = tail_dst + tail_len;
} else
totlen = enc_compute_buf_len(product, version, src_len);
buf = malloc(totlen);
if (buf == NULL) {
ERR("no memory for the buffer");
goto out;
}
hdrlen = enc_compute_header_len(product, version);
err = read_file_to_buf(ifname, &buf[hdrlen], src_len);
if (err) {
ERR("unable to read from file '%s'", ofname);
goto free_buf;
}
if (size) {
tail_src = hdrlen + size;
memmove(&buf[tail_dst], &buf[tail_src], tail_len);
memset(&buf[tail_src], 0, tail_dst - tail_src);
src_len = size;
}
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: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 'S':
size = 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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,141 @@
/*
* 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));
struct buffalo_tag3 {
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 base2;
} __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 */

View File

@@ -0,0 +1,414 @@
/*
* 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;
static int dhp;
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"
" -I <file> read input from the file <file> for DHP series\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 void fixup_tag3(unsigned char *buf, ssize_t totlen)
{
struct buffalo_tag3 *tag = (struct buffalo_tag3 *) 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(totlen);
tag->len1 = htonl(fsize[0]);
tag->base2 = htonl(base2);
if (hwver) {
memcpy(tag->hwv, "hwv", 3);
memcpy(tag->hwv_val, hwver, strlen(hwver));
}
}
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 (dhp)
hdrlen = sizeof(struct buffalo_tag3);
else 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 (dhp)
fixup_tag3(buf, fsize[0] + 200);
else 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:I:");
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':
dhp = 1;
/* FALLTHROUGH */
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;
}

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -0,0 +1,377 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.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;
}

View File

@@ -0,0 +1,166 @@
/* **************************************************************************
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 = 0, sum1 = 0;
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;
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;
}

View File

@@ -0,0 +1,239 @@
/*
* dns313-header.c
*
* Program to add the modified U-Boot header to a binary used with
* the D-Link DNS-313 boot loader when booting directly from an
* EXT2 formatted hard drive.
*
* The DNS313 use the same header on zImage, ramdisk, rootfs.
*
* Written by Linus Walleij <linus.walleij@linaro.org>
* License terms: GPLv2
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*
* This is the U-Boot magic number, so the U-Boot header was used
* (obviously) as a template for this custom header.
*/
#define IH_MAGIC 0x27051956
#define HEADER_SIZE 0x68
#define OFFSET_MAGIC 0x00
#define OFFSET_HCRC 0x04
#define OFFSET_TIME 0x08
#define OFFSET_SIZE 0x0c
#define OFFSET_LOAD 0x10
#define OFFSET_EP 0x14
#define OFFSET_DCRC 0x18
#define OFFSET_OS 0x1c
#define OFFSET_ARCH 0x1d
#define OFFSET_TYPE 0x1e
#define OFFSET_COMP 0x1f
#define OFFSET_NAME 0x20
#define NAME_LEN 0x20
#define OFFSET_MODEL 0x40
#define MODEL_LEN 0x10
#define OFFSET_VERSION 0x50
#define VERSION_LEN 0x10
#define OFFSET_MAC 0x60
#define MAC_LEN 6
static const uint32_t crc32_table[256] = {
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
};
static uint32_t crc32(uint32_t crc,
const unsigned char *buf,
unsigned int len)
{
crc = crc ^ 0xffffffffUL;
do {
crc = crc32_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
} while (--len);
return crc ^ 0xffffffffUL;
}
static void be_wr(unsigned char *buf, uint32_t val)
{
buf[0] = (val >> 24) & 0xFFU;
buf[1] = (val >> 16) & 0xFFU;
buf[2] = (val >> 8) & 0xFFU;
buf[3] = val & 0xFFU;
}
int main(int argc, char **argv)
{
int fdin;
int fdout;
struct stat sb;
uint32_t filesize;
uint32_t padding;
int ret = 0;
const char *pathin;
const char *pathout;
unsigned char *buffer;
unsigned char *infop;
uint32_t sum;
size_t bufsize;
size_t bytes;
int i;
if (argc < 3) {
printf("Too few arguments.\n");
printf("%s <infile> <outfile>\n", argv[0]);
}
pathin = argv[1];
pathout = argv[2];
ret = stat(pathin, &sb);
if (ret < 0)
return ret;
filesize = sb.st_size;
padding = filesize % 4;
printf("INFILE: %s, size: %08x bytes\n", pathin, filesize);
/* File + extended header size */
bufsize = filesize + HEADER_SIZE;
printf("Allocate %08x bytes\n", bufsize);
buffer = malloc(bufsize);
if (!buffer) {
printf("OOM: could not allocate buffer\n");
return 0;
}
memset(buffer, 0x00, bufsize);
/* Read file to buffer */
fdin = open(pathin, O_RDONLY);
if (!fdin) {
printf("ERROR: could not open input file\n");
return 0;
}
bytes = read(fdin, buffer + HEADER_SIZE, filesize);
if (bytes < filesize) {
printf("ERROR: could not read entire file\n");
return 0;
}
close(fdin);
/* PREP HEADER AND FOOTER */
infop = buffer;
be_wr(buffer + OFFSET_MAGIC, IH_MAGIC);
/* FIXME: use actual time */
be_wr(buffer + OFFSET_TIME, 0x4c06738c);
be_wr(buffer + OFFSET_SIZE, filesize);
/* Load address & entry point */
be_wr(buffer + OFFSET_LOAD, 0x00008000);
be_wr(buffer + OFFSET_EP, 0x00008000);
buffer[OFFSET_OS] = 0x05; /* Linux */
buffer[OFFSET_ARCH] = 0x02; /* ARM */
buffer[OFFSET_TYPE] = 0x02; /* OS kernel image */
buffer[OFFSET_COMP] = 0x01; /* gzip */
/* The vendor firmware just hardcodes this */
strncpy(buffer + OFFSET_NAME, "kernel.img", NAME_LEN);
buffer[OFFSET_NAME + NAME_LEN - 1] = '\0';
strncpy(buffer + OFFSET_MODEL, "dns-313v3", MODEL_LEN);
buffer[OFFSET_MODEL + MODEL_LEN - 1] = '\0';
strncpy(buffer + OFFSET_VERSION, "2.01b04", VERSION_LEN);
buffer[OFFSET_VERSION + VERSION_LEN - 1] = '\0';
/* Just some MAC address from the example */
buffer[OFFSET_MAC] = 0x00;
buffer[OFFSET_MAC + 1] = 0x80;
buffer[OFFSET_MAC + 2] = 0xc8;
buffer[OFFSET_MAC + 3] = 0x16;
buffer[OFFSET_MAC + 4] = 0x81;
buffer[OFFSET_MAC + 5] = 0x68;
/* Checksum payload */
sum = crc32(0, buffer + HEADER_SIZE, filesize);
be_wr(buffer + OFFSET_DCRC, sum);
printf("data checksum: 0x%08x\n", sum);
/* Checksum header, then write that into the header checksum */
sum = crc32(0, buffer, HEADER_SIZE);
be_wr(buffer + OFFSET_HCRC, sum);
printf("header checksum: 0x%08x\n", sum);
printf("OUTFILE: %s, size: %08x bytes\n", pathout, bufsize);
fdout = open(pathout, O_RDWR|O_CREAT|O_TRUNC,S_IRWXU|S_IRGRP);
if (!fdout) {
printf("ERROR: could not open output file\n");
return 0;
}
bytes = write(fdout, buffer, bufsize);
if (bytes < bufsize) {
printf("ERROR: could not write complete output file\n");
return 0;
}
close(fdout);
free(buffer);
return 0;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -0,0 +1,203 @@
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <errno.h>
#include <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" );
}
static time_t source_date_epoch = -1;
static void set_source_date_epoch() {
char *env = getenv("SOURCE_DATE_EPOCH");
char *endptr = env;
errno = 0;
if (env && *env) {
source_date_epoch = strtoull(env, &endptr, 10);
if (errno || (endptr && *endptr != '\0')) {
fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
exit(1);
}
}
}
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;
}
time_t t = -1;
set_source_date_epoch();
if (source_date_epoch != -1) {
t = source_date_epoch;
} else if ((time(&t) == (time_t)(-1))) {
fprintf(stderr, "time call failed\n");
return EXIT_FAILURE;
}
struct stat buf;
stat ( input,&buf );
ldr_header_t* head = construct_header ( magicnum, (uint16_t) majrev, (uint16_t) minrev, ( uint32_t ) t, ( 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;
}

View File

@@ -0,0 +1,491 @@
/*
* 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 <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);
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

View File

@@ -0,0 +1,425 @@
/*
* jcgimage - Create a JCG firmware image
*
* Copyright (C) 2015 Reinhard Max <reinhard@m4x.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/*
* JCG firmware update images consist of a 512 byte header and a
* modified uImage (details below) as the payload.
*
* The payload is obfuscated by XORing it with a key that is generated
* from parts of the header. Fortunately only non-essential parts of
* the header are used for this and zeroing them results in a zero
* key, effectively disabling the obfuscation and allowing us to use
* clear text payloads.
*
* The mandatory parts of the header are:
*
* - A magic string of "YSZJ" at offset 0.
* - A value of 1 at offset 39 (header format version?)
* - A CRC32 checksum of the payload at offset 504.
* - A CRC32 checksum of the header at offset 508.
*
* An image constructed by these rules will be accepted by JCG's
* U-Boot in resuce mode via TFTP and the payload will be written to
* the flash starting at offset 0x00050000.
*
* JCG's U-Boot does check the content or size of the payload
* image. If it is too large, it wraps around and overwrites U-Boot,
* requiring JTAG to revive the board. To prevent such bricking from
* happening, this tool refuses to build such overlong images.
*
* Two more conditions have to be met for a JCG image to be accepted
* as a valid update by the web interface of the stock firware:
*
* - The bytes at offsets 109 and 111 in the header must be a binary
* representation of the first two components of the firmware
* version as displayed in the update web form, or it will be
* rejected as "incorrect product".
*
* - The payload must start with a valid uImage header whose data
* CRC checksum matches the whole rest of the update file rather
* than just the number of bytes specified in the size field of the
* header.
*
* This last condition is met by JCG's original firmware images,
* because they have both, kernel and rootfs inside the uImage and
* abuse the last four bytes of the name field to record the offset of
* the file system from the start of the uImage header. This tool
* produces such images when called with -k and -r, which are meant to
* repack the original firmware after modifying the file systen,
* e.g. to add debugging tools and enable shell access.
*
* In contrast, OpenWrt sysupgrade images consist of a uImage that
* only contains the kernel and has the rootfs appended to it. Hence,
* the CRC over kernel and file system does not match the one in the
* uImage header. Fixing this by adjusting the uImage header is not
* possible, because it makes the uImage unusable for booting. Instead
* we append four "patch" bytes to the end of the file system, that
* are calculated to force the checksum of kernel+fs to be the same as
* for the kernel alone.
*
*/
#include <zlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <libgen.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <time.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <assert.h>
/*
* JCG Firmware image header
*/
#define JH_MAGIC 0x59535a4a /* "YSZJ" */
struct jcg_header {
uint32_t jh_magic;
uint8_t jh_version[32]; /* Firmware version string.
Fill with zeros to avoid encryption */
uint32_t jh_type; /* must be 1 */
uint8_t jh_info[64]; /* Firmware info string. Fill with
zeros to avoid encryption */
uint32_t jh_time; /* Image creation time in seconds since
* the Epoch. Does not seem to be used
* by the stock firmware. */
uint16_t jh_major; /* Major fimware version */
uint16_t jh_minor; /* Minor fimrmware version */
uint8_t jh_unknown[392]; /* Apparently unused and all zeros */
uint32_t jh_dcrc; /* CRC checksum of the payload */
uint32_t jh_hcrc; /* CRC checksum of the header */
};
/*
* JCG uses a modified uImage header that replaces the last four bytes
* of the image name with the length of the kernel in the image.
*/
#define IH_MAGIC 0x27051956 /* Image Magic Number */
#define IH_NMLEN 28 /* Image Name Length */
struct uimage_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 */
uint32_t ih_fsoff; /* Offset of the file system
partition from the start of
the header */
};
/*
* Open the named file and return its size and file descriptor.
* Exit in case of errors.
*/
int
opensize(char *name, size_t *size)
{
struct stat s;
int fd = open(name, O_RDONLY);
if (fd < 0) {
err(1, "cannot open \"%s\"", name);
}
if (fstat(fd, &s) == -1) {
err(1, "cannot stat \"%s\"", name);
}
*size = s.st_size;
return fd;
}
static time_t source_date_epoch = -1;
static void set_source_date_epoch() {
char *env = getenv("SOURCE_DATE_EPOCH");
char *endptr = env;
errno = 0;
if (env && *env) {
source_date_epoch = strtoull(env, &endptr, 10);
if (errno || (endptr && *endptr != '\0')) {
fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
exit(1);
}
}
}
/*
* Write the JCG header
*/
void
mkjcgheader(struct jcg_header *h, size_t psize, char *version)
{
uLong crc;
uint16_t major = 0, minor = 0;
void *payload = (void *)h + sizeof(*h);
time_t t;
if (source_date_epoch != -1) {
t = source_date_epoch;
} else if ((time(&t) == (time_t)(-1))) {
err(1, "time call failed");
}
if (version != NULL) {
if (sscanf(version, "%hu.%hu", &major, &minor) != 2) {
err(1, "cannot parse version \"%s\"", version);
}
}
memset(h, 0, sizeof(*h));
h->jh_magic = htonl(JH_MAGIC);
h->jh_type = htonl(1);
h->jh_time = htonl(t);
h->jh_major = htons(major);
h->jh_minor = htons(minor);
/* CRC over JCG payload (uImage) */
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, payload, psize);
h->jh_dcrc = htonl(crc);
/* CRC over JCG header */
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, (void *)h, sizeof(*h));
h->jh_hcrc = htonl(crc);
}
/*
* Write the uImage header
*/
void
mkuheader(struct uimage_header *h, size_t ksize, size_t fsize)
{
uLong crc;
void *payload = (void *)h + sizeof(*h);
// printf("mkuheader: %p, %zd, %zd\n", h, ksize, fsize);
memset(h, 0, sizeof(*h));
h->ih_magic = htonl(IH_MAGIC);
h->ih_time = htonl(time(NULL));
h->ih_size = htonl(ksize + fsize);
h->ih_load = htonl(0x80000000);
h->ih_ep = htonl(0x80292000);
h->ih_os = 0x05;
h->ih_arch = 0x05;
h->ih_type = 0x02;
h->ih_comp = 0x03;
h->ih_fsoff = htonl(sizeof(*h) + ksize);
strcpy((char *)h->ih_name, "Linux Kernel Image");
/* CRC over uImage payload (kernel and file system) */
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, payload, ntohl(h->ih_size));
h->ih_dcrc = htonl(crc);
printf("CRC1: %08lx\n", crc);
/* CRC over uImage header */
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, (void *)h, sizeof(*h));
h->ih_hcrc = htonl(crc);
printf("CRC2: %08lx\n", crc);
}
/*
* Calculate a "patch" value and write it into the last four bytes of
* buf, so that the CRC32 checksum of the whole buffer is dcrc.
*
* Based on: SAR-PR-2006-05: Reversing CRC Theory and Practice.
* Martin Stigge, Henryk Plötz, Wolf Müller, Jens-Peter Redlich.
* http://sar.informatik.hu-berlin.de/research/publications/#SAR-PR-2006-05
*/
void
craftcrc(uint32_t dcrc, uint8_t *buf, size_t len)
{
int i;
uint32_t a;
uint32_t patch = 0;
uint32_t crc = crc32(0L, Z_NULL, 0);
a = ~dcrc;
for (i = 0; i < 32; i++) {
if (patch & 1) {
patch = (patch >> 1) ^ 0xedb88320L;
} else {
patch >>= 1;
}
if (a & 1) {
patch ^= 0x5b358fd3L;
}
a >>= 1;
}
patch ^= ~crc32(crc, buf, len - 4);
for (i = 0; i < 4; i++) {
buf[len - 4 + i] = patch & 0xff;
patch >>= 8;
}
/* Verify that we actually get the desired result */
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, buf, len);
if (crc != dcrc) {
errx(1, "CRC patching is broken: wanted %08x, but got %08x.",
dcrc, crc);
}
}
void
usage() {
fprintf(stderr, "Usage:\n"
"jcgimage -o outfile -u uImage [-v version]\n"
"jcgimage -o outfile -k kernel -f rootfs [-v version]\n");
exit(1);
}
#define MODE_UNKNOWN 0
#define MODE_UIMAGE 1
#define MODE_KR 2
/* The output image must not be larger than 4MiB - 5*64kiB */
#define MAXSIZE (size_t)(4 * 1024 * 1024 - 5 * 64 * 1024)
int
main(int argc, char **argv)
{
struct jcg_header *jh;
struct uimage_header *uh;
int c;
char *imagefile = NULL;
char *file1 = NULL;
char *file2 = NULL;
char *version = NULL;
int mode = MODE_UNKNOWN;
int fdo, fd1, fd2;
size_t size1, size2, sizeu, sizeo, off1, off2;
void *map;
/* Make sure the headers have the right size */
assert(sizeof(struct jcg_header) == 512);
assert(sizeof(struct uimage_header) == 64);
set_source_date_epoch();
while ((c = getopt(argc, argv, "o:k:f:u:v:h")) != -1) {
switch (c) {
case 'o':
imagefile = optarg;
break;
case 'k':
if (mode == MODE_UIMAGE) {
errx(1,"-k cannot be combined with -u");
}
mode = MODE_KR;
file1 = optarg;
break;
case 'f':
if (mode == MODE_UIMAGE) {
errx(1,"-f cannot be combined with -u");
}
mode = MODE_KR;
file2 = optarg;
break;
case 'u':
if (mode == MODE_KR) {
errx(1,"-u cannot be combined with -k and -r");
}
mode = MODE_UIMAGE;
file1 = optarg;
break;
case 'v':
version = optarg;
break;
case 'h':
default:
usage();
}
}
if (optind != argc) {
errx(1, "illegal arg \"%s\"", argv[optind]);
}
if (imagefile == NULL) {
errx(1, "no output file specified");
}
if (mode == MODE_UNKNOWN) {
errx(1, "specify either -u or -k and -r");
}
if (mode == MODE_KR) {
if (file1 == NULL || file2 == NULL) {
errx(1,"need -k and -r");
}
fd2 = opensize(file2, &size2);
}
fd1 = opensize(file1, &size1);
if (mode == MODE_UIMAGE) {
off1 = sizeof(*jh);
sizeu = size1 + 4;
sizeo = sizeof(*jh) + sizeu;
} else {
off1 = sizeof(*jh) + sizeof(*uh);
off2 = sizeof(*jh) + sizeof(*uh) + size1;
sizeu = sizeof(*uh) + size1 + size2;
sizeo = sizeof(*jh) + sizeu;
}
if (sizeo > MAXSIZE) {
errx(1,"payload too large: %zd > %zd\n", sizeo, MAXSIZE);
}
fdo = open(imagefile, O_RDWR | O_CREAT | O_TRUNC, 00644);
if (fdo < 0) {
err(1, "cannot open \"%s\"", imagefile);
}
if (ftruncate(fdo, sizeo) == -1) {
err(1, "cannot grow \"%s\" to %zd bytes", imagefile, sizeo);
}
map = mmap(NULL, sizeo, PROT_READ|PROT_WRITE, MAP_SHARED, fdo, 0);
uh = map + sizeof(*jh);
if (map == MAP_FAILED) {
err(1, "cannot mmap \"%s\"", imagefile);
}
if (read(fd1, map + off1, size1) != size1) {
err(1, "cannot copy %s", file1);
}
if (mode == MODE_KR) {
if (read(fd2, map+off2, size2) != size2) {
err(1, "cannot copy %s", file2);
}
mkuheader(uh, size1, size2);
} else if (mode == MODE_UIMAGE) {
craftcrc(ntohl(uh->ih_dcrc), (void*)uh + sizeof(*uh),
sizeu - sizeof(*uh));
}
mkjcgheader(map, sizeu, version);
munmap(map, sizeo);
close(fdo);
return 0;
}

View File

@@ -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 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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,296 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#ifndef HAVE_OPENSSL
#include <string.h>
#include "md5.h"
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
/*
* SET reads 4 input bytes in little-endian byte order and stores them
* in a properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned
* memory accesses is just an optimization. Nothing will break if it
* doesn't work.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update
* the bit counters. There are no alignment requirements.
*/
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void MD5_Init(MD5_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used) {
available = 64 - used;
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
ctx->buffer[56] = ctx->lo;
ctx->buffer[57] = ctx->lo >> 8;
ctx->buffer[58] = ctx->lo >> 16;
ctx->buffer[59] = ctx->lo >> 24;
ctx->buffer[60] = ctx->hi;
ctx->buffer[61] = ctx->hi >> 8;
ctx->buffer[62] = ctx->hi >> 16;
ctx->buffer[63] = ctx->hi >> 24;
body(ctx, ctx->buffer, 64);
result[0] = ctx->a;
result[1] = ctx->a >> 8;
result[2] = ctx->a >> 16;
result[3] = ctx->a >> 24;
result[4] = ctx->b;
result[5] = ctx->b >> 8;
result[6] = ctx->b >> 16;
result[7] = ctx->b >> 24;
result[8] = ctx->c;
result[9] = ctx->c >> 8;
result[10] = ctx->c >> 16;
result[11] = ctx->c >> 24;
result[12] = ctx->d;
result[13] = ctx->d >> 8;
result[14] = ctx->d >> 16;
result[15] = ctx->d >> 24;
memset(ctx, 0, sizeof(*ctx));
}
#endif

View File

@@ -0,0 +1,45 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2016 FUKAUMI Naoki <naobsd@gmail.com>
*
* Based on mkdniimg.c
*
* 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 = "0.00_0.00";
static char *region = "JP";
static char *rootfs_size;
static char *kernel_size;
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;
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"
" -R <rootfs_size> set RootfsSize to <rootfs_size>\n"
" -K <kernel_size> set KernelSize to <kernel_size>\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 i;
uint8_t csum;
FILE *outfile, *infile;
progname = basename(argv[0]);
while ( 1 ) {
int c;
c = getopt(argc, argv, "B:i:o:v:r:R:K: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 'R':
rootfs_size = optarg;
break;
case 'K':
kernel_size = optarg;
break;
case 'h':
usage(EXIT_SUCCESS);
break;
default:
usage(EXIT_FAILURE);
break;
}
}
if (board_id == NULL) {
ERR("no board specified");
goto err;
}
if (rootfs_size == NULL) {
ERR("no rootfs_size specified");
goto err;
}
if (kernel_size == NULL) {
ERR("no kernel_size 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);
snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:%s\nregion:%s\n"
"RootfsSize:%s\nKernelSize:%s\nInfoHeadSize:128\n",
board_id, version, region, rootfs_size, kernel_size);
buf[DNI_HDR_LEN - 2] = 0x12;
buf[DNI_HDR_LEN - 1] = 0x32;
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;
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;
}

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,341 @@
/*
* 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)
/*
* Note on the reserved field of the chk_header:
* OFW naming scheme is typically: DEVICENAME-VA.B.C.D_E.F.G.chk, with A-G
* between 0 and 255. For instance: EX3700_EX3800-V1.0.0.58_1.0.38.chk
* The reserved field works like this:
* reserved[0]: region code. 1 for WW (WorldWide) and 2 for NA (North America)
* reserved[1]: A
* reserved[2]: B
* reserved[3]: C
* reserved[4]: D
* reserved[5]: E
* reserved[6]: F
* reserved[7]: G
*/
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;
hdr->reserved[5] = 0;
hdr->reserved[6] = 0;
hdr->reserved[7] = 0;
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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 sysupgrade.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);
}

View File

@@ -0,0 +1,204 @@
/*
* 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) Nicolò Veronese <nicveronese@gmail.com>
*/
#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: mkdapimg2 -s signature [-v version] [-r region]
// [-k uImage block size] -i <input> -o <output>
//
// NOTE: The kernel block size is used to know the offset of the rootfs
// in the image file.
//
// The system writes in the uImage partition until the end of uImage
// is reached, after that, the system jumps to the offset specified with the -k
// parameter and begin writing at the beginning of the rootfs MTD partition.
//
// If the -k parameter is the size of the original uImage partition, the system
// continue writing in the rootfs partition starting from the last block
// that has been wrote. (This is useful if the new kernel size is
// different from the original one)
//
// Example:
// ------------------------------------------
// Creating 7 MTD partitions on "ath-nor0":
// 0x000000000000-0x000000010000 : "u-boot"
// 0x000000010000-0x000000020000 : "ART"
// 0x000000020000-0x000000030000 : "MP"
// 0x000000030000-0x000000040000 : "config"
// 0x000000040000-0x000000120000 : "uImage"
// 0x000000120000-0x000000800000 : "rootfs"
// 0x000000040000-0x000000800000 : "firmware"
// ------------------------------------------
//
// 0x000000120000-0x000000040000 = 0xE0000 -> 917504
//
// e.g.: mkdapimg2 -s HONEYBEE-FIRMWARE-DAP-1330 -v 1.00.21 -r Default
// -k 917504 -i sysupgrade.bin -o factory.bin
//
//
// The img_hdr_struct was taken from the D-Link SDK:
// DAP-1330_OSS-firmware_1.00b21/DAP-1330_OSS-firmware_1.00b21/uboot/uboot.patch
#define MAX_SIGN_LEN 32
#define MAX_FW_VER_LEN 16
#define MAX_REG_LEN 8
struct img_hdr_struct {
uint32_t hdr_len;
uint32_t checksum;
uint32_t total_size;
uint32_t kernel_size;
char signature[MAX_SIGN_LEN];
char fw_ver[MAX_FW_VER_LEN];
char fw_reg[MAX_REG_LEN];
} 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 -s signature [-v version] [-r region] [-k uImage part size] -i <input> -o <output>\n", progname);
exit(1);
}
int
main(int ac, char *av[])
{
char signature[MAX_SIGN_LEN];
char version[MAX_FW_VER_LEN];
char region[MAX_REG_LEN];
int kernel = 0;
FILE *ifile, *ofile;
int c;
uint32_t cksum;
uint32_t bcnt;
progname = basename(av[0]);
memset(signature, 0, sizeof(signature));
memset(version, 0, sizeof(version));
memset(region, 0, sizeof(region));
while ( 1 ) {
char *ptr;
int c;
c = getopt(ac, av, "s:v:r:k:i:o:");
if (c == -1)
break;
switch (c) {
case 's':
if (strlen(optarg) > MAX_SIGN_LEN + 1) {
fprintf(stderr, "%s: signature exceeds %d chars\n",
progname, MAX_SIGN_LEN);
exit(1);
}
strcpy(signature, optarg);
break;
case 'v':
if (strlen(optarg) > MAX_FW_VER_LEN + 1) {
fprintf(stderr, "%s: version exceeds %d chars\n",
progname, MAX_FW_VER_LEN);
exit(1);
}
strcpy(version, optarg);
break;
case 'r':
if (strlen(optarg) > MAX_REG_LEN + 1) {
fprintf(stderr, "%s: region exceeds %d chars\n",
progname, MAX_REG_LEN);
exit(1);
}
strcpy(region, optarg);
break;
case 'k':
kernel = strtoul(optarg, &ptr, 0);
if(ptr[0] == 'k'){
kernel *= 1000;
}
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();
exit(1);
}
for (bcnt = 0, cksum = 0 ; (c = fgetc(ifile)) != EOF ; bcnt++)
cksum += c & 0xff;
if (fseek(ifile, 0, SEEK_SET) < 0)
perrexit(2, "fseek on input");
// Fill in the header
memset(&imghdr, 0, sizeof(imghdr));
imghdr.hdr_len = sizeof(imghdr);
imghdr.checksum = htonl(cksum);
imghdr.total_size = htonl(bcnt);
imghdr.kernel_size = htonl(kernel);
strncpy(imghdr.signature, signature, MAX_SIGN_LEN);
strncpy(imghdr.fw_ver, version, MAX_FW_VER_LEN);
strncpy(imghdr.fw_reg, region, MAX_REG_LEN);
if (fwrite(&imghdr, sizeof(imghdr), 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);
fprintf(stderr, "imgHdr.hdr_len = %lu\n", sizeof(imghdr));
fprintf(stderr, "imgHdr.checksum = 0x%08x\n", cksum);
fprintf(stderr, "imgHdr.total_size = 0x%08x\n", bcnt);
fprintf(stderr, "imgHdr.kernel_size = 0x%08x\n", kernel);
fprintf(stderr, "imgHdr.header = %s\n", signature);
fprintf(stderr, "imgHdr.fw_ver = %s\n", version);
fprintf(stderr, "imgHdr.fw_reg = %s\n", region);
return 0;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2016 FUKAUMI Naoki <naobsd@gmail.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 <sys/stat.h>
#include <err.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "buffalo-lib.h"
#define DHP_HEADER_SIZE 20
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s <in> <out>\n", progname);
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
struct stat in_st;
size_t size;
uint32_t crc;
int in, out;
uint8_t *buf;
progname = argv[0];
if (argc != 3)
usage();
if ((in = open(argv[1], O_RDONLY)) == -1)
err(EXIT_FAILURE, "%s", argv[1]);
if (fstat(in, &in_st) == -1)
err(EXIT_FAILURE, "%s", argv[1]);
size = DHP_HEADER_SIZE + in_st.st_size;
if ((buf = malloc(size)) == NULL)
err(EXIT_FAILURE, "malloc");
memset(buf, 0, DHP_HEADER_SIZE);
buf[0x0] = 0x62;
buf[0x1] = 0x67;
buf[0x2] = 0x6e;
buf[0xb] = 0xb1;
buf[0xc] = (size >> 24) & 0xff;
buf[0xd] = (size >> 16) & 0xff;
buf[0xe] = (size >> 8) & 0xff;
buf[0xf] = size & 0xff;
read(in, &buf[DHP_HEADER_SIZE], in_st.st_size);
close(in);
crc = buffalo_crc(buf, size);
buf[0x10] = (crc >> 24) & 0xff;
buf[0x11] = (crc >> 16) & 0xff;
buf[0x12] = (crc >> 8) & 0xff;
buf[0x13] = crc & 0xff;
if ((out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
err(EXIT_FAILURE, "%s", argv[2]);
write(out, buf, size);
close(out);
free(buf);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,172 @@
/*
* mkdlinkfw
*
* Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
*
* This tool is based on mktplinkfw.
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
* 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 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 <stdint.h>
#include <string.h>
#include <unistd.h> /* for unlink() */
#include <libgen.h>
#include <getopt.h> /* for getopt() */
#include <stdarg.h>
#include <stdbool.h>
#include <endian.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <zlib.h> /*for crc32 */
#include "mkdlinkfw-lib.h"
extern char *progname;
static unsigned char jffs2_eof_mark[4] = { 0xde, 0xad, 0xc0, 0xde };
uint32_t jboot_timestamp(void)
{
time_t rawtime;
time(&rawtime);
return (((uint32_t) rawtime) - TIMESTAMP_MAGIC) >> 2;
}
uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size)
{
uint32_t counter = start_val;
uint16_t *ptr = data;
while (size > 1) {
counter += *ptr;
++ptr;
while (counter >> 16)
counter = (uint16_t) counter + (counter >> 16);
size -= 2;
}
if (size > 0) {
counter += *(uint8_t *) ptr;
counter -= 0xFF;
}
while (counter >> 16)
counter = (uint16_t) counter + (counter >> 16);
return counter;
}
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;
}
int read_to_buf(const 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;
}
int pad_jffs2(char *buf, int currlen, int maxlen)
{
int len;
uint32_t pad_mask;
len = currlen;
pad_mask = (4 * 1024) | (64 * 1024); /* EOF at 4KB and at 64KB */
while ((len < maxlen) && (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;
}
int write_fw(const char *ofname, const 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;
}

View File

@@ -0,0 +1,83 @@
/*
* mkdlinkfw
*
* Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
*
* This tool is based on mktplinkfw.
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
* 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 as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#ifndef mkdlinkfw_lib_h
#define mkdlinkfw_lib_h
#define AUH_MAGIC "DLK"
#define AUH_SIZE 80
#define AUH_LVPS 0x01
#define AUH_HDR_ID 0x4842
#define AUH_HDR_VER 0x02
#define AUH_SEC_ID 0x04
#define AUH_INFO_TYPE 0x04
#define STAG_SIZE 16
#define STAG_ID 0x04
#define STAG_MAGIC 0x2B24
#define STAG_CMARK_FACTORY 0xFF
#define SCH2_SIZE 40
#define SCH2_MAGIC 0x2124
#define SCH2_VER 0x02
#define FLAT 0
#define JZ 1
#define GZIP 2
#define LZMA 3
#define RAM_ENTRY_ADDR 0x80000000
#define RAM_LOAD_ADDR 0x80000000
#define JBOOT_SIZE 0x10000
#define ALL_HEADERS_SIZE (AUH_SIZE + STAG_SIZE + SCH2_SIZE)
#define MAX_HEADER_COUNTER 10
#define TIMESTAMP_MAGIC 0x35016f00L
#define FACTORY 0
#define SYSUPGRADE 1
#define ALIGN(x, a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
#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)
struct file_info {
char *file_name; /* name of the file */
uint32_t file_size; /* length of the file */
};
uint32_t jboot_timestamp(void);
uint16_t jboot_checksum(uint16_t start_val, uint16_t *data, int size);
int get_file_stat(struct file_info *fdata);
int read_to_buf(const struct file_info *fdata, char *buf);
int pad_jffs2(char *buf, int currlen, int maxlen);
int write_fw(const char *ofname, const char *data, int len);
#endif /* mkdlinkfw_lib_h */

View File

@@ -0,0 +1,665 @@
/*
* mkdlinkfw
*
* Copyright (C) 2018 Paweł Dembicki <paweldembicki@gmail.com>
*
* This tool is based on mktplinkfw.
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
* 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 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 <stdint.h>
#include <string.h>
#include <unistd.h> /* for unlink() */
#include <libgen.h>
#include <getopt.h> /* for getopt() */
#include <stdarg.h>
#include <stdbool.h>
#include <endian.h>
#include <errno.h>
#include <sys/stat.h>
#include <zlib.h> /*for crc32 */
#include "mkdlinkfw-lib.h"
/* ARM update header 2.0
* used only in factory images to erase and flash selected area
*/
struct auh_header {
uint8_t rom_id[12]; /* 12-bit rom-id unique per router type */
uint16_t derange; /* used for scramble header */
uint16_t image_checksum; /* jboot_checksum of flashed data */
uint32_t space1; /* zeros */
uint32_t space2; /* zeros */
uint16_t space3; /* zerosu */
uint8_t lpvs; /* must be 0x01 */
uint8_t mbz; /* bust be 0 */
uint32_t time_stamp; /* timestamp calculated in jboot way */
uint32_t erase_start; /* erase start address */
uint32_t erase_length; /* erase length address */
uint32_t data_offset; /* data start address */
uint32_t data_length; /* data length address */
uint32_t space4; /* zeros */
uint32_t space5; /* zeros */
uint32_t space6; /* zeros */
uint32_t space7; /* zeros */
uint16_t header_id; /* magic 0x4842 */
uint16_t header_version; /* 0x02 for 2.0 */
uint16_t space8; /* zeros */
uint8_t section_id; /* section id */
uint8_t image_info_type; /* (?) 0x04 in factory images */
uint32_t image_info_offset; /* (?) zeros in factory images */
uint16_t family_member; /* unique per router type */
uint16_t header_checksum; /* negated jboot_checksum of header data */
};
struct stag_header { /* used only of sch2 wrapped kernel data */
uint8_t cmark; /* in factory 0xFF ,in sysuograde must be the same as id */
uint8_t id; /* 0x04 */
uint16_t magic; /* magic 0x2B24 */
uint32_t time_stamp; /* timestamp calculated in jboot way */
uint32_t image_length; /* lentgh of kernel + sch2 header */
uint16_t image_checksum; /* negated jboot_checksum of sch2 + kernel */
uint16_t tag_checksum; /* negated jboot_checksum of stag header data */
};
struct sch2_header { /* used only in kernel partitions */
uint16_t magic; /* magic 0x2124 */
uint8_t cp_type; /* 0x00 for flat, 0x01 for jz, 0x02 for gzip, 0x03 for lzma */
uint8_t version; /* 0x02 for sch2 */
uint32_t ram_addr; /* ram entry address */
uint32_t image_len; /* kernel image length */
uint32_t image_crc32; /* kernel image crc */
uint32_t start_addr; /* ram start address */
uint32_t rootfs_addr; /* rootfs flash address */
uint32_t rootfs_len; /* rootfls length */
uint32_t rootfs_crc32; /* rootfs crc32 */
uint32_t header_crc32; /* sch2 header crc32, durring calculation this area is replaced by zero */
uint16_t header_length; /* sch2 header length: 0x28 */
uint16_t cmd_line_length; /* cmd line length, known zeros */
};
/* globals */
static struct file_info inspect_info;
struct file_info kernel_info;
struct file_info rootfs_info;
struct file_info image_info;
char *ofname;
char *progname;
uint32_t firmware_size;
uint16_t family_member;
char *rom_id[12] = { 0 };
char image_type;
int add_jffs2_eof;
static void usage(int status)
{
fprintf(stderr, "Usage: %s [OPTIONS...]\n", progname);
fprintf(stderr,
"\n"
"Options:\n"
" -i <file> inspect given firmware file <file>\n"
" -f set family member id (hexval prefixed with 0x)\n"
" -F <file> read image and convert it to FACTORY\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"
" -s <size> set firmware partition size\n"
" -m <version> set rom id to <version> (12-bit string val: \"DLK*********\")\n"
" -h show this screen\n");
exit(status);
}
void print_auh_header(struct auh_header *printed_header)
{
printf("\trom_id: %s\n"
"\tderange: 0x%04X\n"
"\timage_checksum: 0x%04X\n"
"\tspace1: 0x%08X\n"
"\tspace2: 0x%08X\n"
"\tspace3: 0x%04X\n"
"\tlpvs: 0x%02X\n"
"\tmbz: 0x%02X\n"
"\ttime_stamp: 0x%08X\n"
"\terase_start: 0x%08X\n"
"\terase_length: 0x%08X\n"
"\tdata_offset: 0x%08X\n"
"\tdata_length: 0x%08X\n"
"\tspace4: 0x%08X\n"
"\tspace5: 0x%08X\n"
"\tspace6: 0x%08X\n"
"\tspace7: 0x%08X\n"
"\theader_id: 0x%04X\n"
"\theader_version: 0x%02X\n"
"\tspace8: 0x%04X\n"
"\tsection_id: 0x%02X\n"
"\timage_info_type: 0x%02X\n"
"\timage_info_offset 0x%08X\n"
"\tfamily_member: 0x%04X\n"
"\theader_checksum: 0x%04X\n",
printed_header->rom_id,
printed_header->derange,
printed_header->image_checksum,
printed_header->space1,
printed_header->space2,
printed_header->space3,
printed_header->lpvs,
printed_header->mbz,
printed_header->time_stamp,
printed_header->erase_start,
printed_header->erase_length,
printed_header->data_offset,
printed_header->data_length,
printed_header->space4,
printed_header->space5,
printed_header->space6,
printed_header->space7,
printed_header->header_id,
printed_header->header_version,
printed_header->space8,
printed_header->section_id,
printed_header->image_info_type,
printed_header->image_info_offset,
printed_header->family_member, printed_header->header_checksum);
}
void print_stag_header(struct stag_header *printed_header)
{
printf("\tcmark: 0x%02X\n"
"\tid: 0x%02X\n"
"\tmagic: 0x%04X\n"
"\ttime_stamp: 0x%08X\n"
"\timage_length: 0x%04X\n"
"\timage_checksum: 0x%04X\n"
"\ttag_checksum: 0x%04X\n",
printed_header->cmark,
printed_header->id,
printed_header->magic,
printed_header->time_stamp,
printed_header->image_length,
printed_header->image_checksum, printed_header->tag_checksum);
}
void print_sch2_header(struct sch2_header *printed_header)
{
printf("\tmagic: 0x%04X\n"
"\tcp_type: 0x%02X\n"
"\tversion: 0x%02X\n"
"\tram_addr: 0x%08X\n"
"\timage_len: 0x%08X\n"
"\timage_crc32: 0x%08X\n"
"\tstart_addr: 0x%08X\n"
"\trootfs_addr: 0x%08X\n"
"\trootfs_len: 0x%08X\n"
"\trootfs_crc32: 0x%08X\n"
"\theader_crc32: 0x%08X\n"
"\theader_length: 0x%04X\n"
"\tcmd_line_length: 0x%04X\n",
printed_header->magic,
printed_header->cp_type,
printed_header->version,
printed_header->ram_addr,
printed_header->image_len,
printed_header->image_crc32,
printed_header->start_addr,
printed_header->rootfs_addr,
printed_header->rootfs_len,
printed_header->rootfs_crc32,
printed_header->header_crc32,
printed_header->header_length, printed_header->cmd_line_length);
}
static int find_auh_headers(char *buf)
{
char *tmp_buf = buf;
struct auh_header *tmp_header[MAX_HEADER_COUNTER];
int header_counter = 0;
int ret = EXIT_FAILURE;
while (tmp_buf - buf <= inspect_info.file_size - AUH_SIZE) {
if (!memcmp(tmp_buf, AUH_MAGIC, 3)) {
if (((struct auh_header *)tmp_buf)->header_checksum ==
(uint16_t) ~jboot_checksum(0, (uint16_t *) tmp_buf,
AUH_SIZE - 2)) {
uint16_t checksum = 0;
printf("Find proper AUH header at: 0x%lX!\n",
tmp_buf - buf);
tmp_header[header_counter] =
(struct auh_header *)tmp_buf;
checksum =
jboot_checksum(0, (uint16_t *) ((char *)
tmp_header
[header_counter]
+ AUH_SIZE),
tmp_header
[header_counter]->data_length);
if (tmp_header[header_counter]->image_checksum
== checksum)
printf("Image checksum ok.\n");
else
ERR("Image checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", tmp_header[header_counter]->image_checksum, checksum);
header_counter++;
if (header_counter > MAX_HEADER_COUNTER)
break;
}
}
tmp_buf++;
}
if (header_counter == 0)
ERR("Can't find proper AUH header!\n");
else if (header_counter > MAX_HEADER_COUNTER)
ERR("To many AUH headers!\n");
else {
for (int i = 0; i < header_counter; i++) {
printf("AUH %d:\n", i);
print_auh_header(tmp_header[i]);
}
ret = EXIT_SUCCESS;
}
return ret;
}
static int check_stag_header(char *buf, struct stag_header *header)
{
int ret = EXIT_FAILURE;
uint8_t cmark_tmp = header->cmark;
header->cmark = header->id;
if (header->tag_checksum ==
(uint16_t) ~jboot_checksum(0, (uint16_t *) header,
STAG_SIZE - 2)) {
uint16_t checksum = 0;
printf("Find proper STAG header at: 0x%lX!\n",
(char *)header - buf);
checksum =
jboot_checksum(0, (uint16_t *) ((char *)header + STAG_SIZE),
header->image_length);
if (header->image_checksum == checksum) {
printf("Image checksum ok.\n");
header->cmark = cmark_tmp;
print_stag_header(header);
ret = EXIT_SUCCESS;
} else
ERR("Image checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", header->image_checksum, checksum);
} else
ERR("STAG header checksum incorrect!");
header->cmark = cmark_tmp;
return ret;
}
static int check_sch2_header(char *buf, struct sch2_header *header)
{
int ret = EXIT_FAILURE;
uint32_t crc32_tmp = header->header_crc32;
header->header_crc32 = 0;
if (crc32_tmp == crc32(0, (uint8_t *) header, header->header_length)) {
uint32_t crc32_val;
printf("Find proper SCH2 header at: 0x%lX!\n",
(char *)header - buf);
crc32_val =
crc32(0, (uint8_t *) header + header->header_length,
header->image_len);
if (header->image_crc32 == crc32_val) {
printf("Kernel checksum ok.\n");
header->header_crc32 = crc32_tmp;
print_sch2_header(header);
ret = EXIT_SUCCESS;
} else
ERR("Kernel checksum incorrect! Stored: 0x%X Calculated: 0x%X\n", header->image_crc32, crc32_val);
} else
ERR("SCH2 header checksum incorrect!");
header->header_crc32 = crc32_tmp;
return ret;
}
static int inspect_fw(void)
{
char *buf;
struct stag_header *stag_header_kernel;
struct sch2_header *sch2_header_kernel;
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;
ret = find_auh_headers(buf);
if (ret)
goto out_free_buf;
stag_header_kernel = (struct stag_header *)(buf + AUH_SIZE);
ret = check_stag_header(buf, stag_header_kernel);
if (ret)
goto out_free_buf;
sch2_header_kernel = (struct sch2_header *)(buf + AUH_SIZE + STAG_SIZE);
ret = check_sch2_header(buf, sch2_header_kernel);
if (ret)
goto out_free_buf;
out_free_buf:
free(buf);
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;
}
return 0;
}
int fill_sch2(struct sch2_header *header, char *kernel_ptr, char *rootfs_ptr)
{
header->magic = SCH2_MAGIC;
header->cp_type = LZMA;
header->version = SCH2_VER;
header->ram_addr = RAM_LOAD_ADDR;
header->image_len = kernel_info.file_size;
header->image_crc32 = crc32(0, (uint8_t *) kernel_ptr, kernel_info.file_size);
header->start_addr = RAM_ENTRY_ADDR;
header->rootfs_addr =
JBOOT_SIZE + STAG_SIZE + SCH2_SIZE + kernel_info.file_size;
header->rootfs_len = rootfs_info.file_size;
header->rootfs_crc32 = crc32(0, (uint8_t *) rootfs_ptr, rootfs_info.file_size);
header->header_crc32 = 0;
header->header_length = SCH2_SIZE;
header->cmd_line_length = 0;
header->header_crc32 = crc32(0, (uint8_t *) header, header->header_length);
return EXIT_SUCCESS;
}
int fill_stag(struct stag_header *header, uint32_t length)
{
header->cmark = STAG_ID;
header->id = STAG_ID;
header->magic = STAG_MAGIC;
header->time_stamp = jboot_timestamp();
header->image_length = length + SCH2_SIZE;
header->image_checksum =
jboot_checksum(0, (uint16_t *) ((char *)header + STAG_SIZE),
header->image_length);
header->tag_checksum =
~jboot_checksum(0, (uint16_t *) header, STAG_SIZE - 2);
if (image_type == FACTORY)
header->cmark = STAG_CMARK_FACTORY;
return EXIT_SUCCESS;
};
int fill_auh(struct auh_header *header, uint32_t length)
{
memcpy(header->rom_id, rom_id, 12);
header->derange = 0;
header->image_checksum =
jboot_checksum(0, (uint16_t *) ((char *)header + AUH_SIZE), length);
header->space1 = 0;
header->space2 = 0;
header->space3 = 0;
header->lpvs = AUH_LVPS;
header->mbz = 0;
header->time_stamp = jboot_timestamp();
header->erase_start = JBOOT_SIZE;
header->erase_length = firmware_size;
header->data_offset = JBOOT_SIZE;
header->data_length = length;
header->space4 = 0;
header->space5 = 0;
header->space6 = 0;
header->space7 = 0;
header->header_id = AUH_HDR_ID;
header->header_version = AUH_HDR_VER;
header->space8 = 0;
header->section_id = AUH_SEC_ID;
header->image_info_type = AUH_INFO_TYPE;
header->image_info_offset = 0;
header->family_member = family_member;
header->header_checksum =
~jboot_checksum(0, (uint16_t *) header, AUH_SIZE - 2);
return EXIT_SUCCESS;
}
int build_fw(void)
{
char *buf;
char *kernel_ptr;
char *rootfs_ptr;
int ret = EXIT_FAILURE;
int writelen;
struct stag_header *stag_header_kernel;
struct sch2_header *sch2_header_kernel;
if (!kernel_info.file_name | !rootfs_info.file_name)
goto out;
ret = get_file_stat(&kernel_info);
if (ret)
goto out;
ret = get_file_stat(&rootfs_info);
if (ret)
goto out;
buf = malloc(firmware_size);
if (!buf) {
ERR("no memory for buffer\n");
goto out;
}
if (rootfs_info.file_size + kernel_info.file_size + ALL_HEADERS_SIZE >
firmware_size) {
ERR("data is bigger than firmware_size!\n");
goto out;
}
memset(buf, 0xff, firmware_size);
stag_header_kernel = (struct stag_header *)buf;
sch2_header_kernel =
(struct sch2_header *)((char *)stag_header_kernel + STAG_SIZE);
kernel_ptr = (char *)sch2_header_kernel + SCH2_SIZE;
ret = read_to_buf(&kernel_info, kernel_ptr);
if (ret)
goto out_free_buf;
rootfs_ptr = kernel_ptr + kernel_info.file_size;
ret = read_to_buf(&rootfs_info, rootfs_ptr);
if (ret)
goto out_free_buf;
writelen = rootfs_ptr + rootfs_info.file_size - buf;
fill_sch2(sch2_header_kernel, kernel_ptr, rootfs_ptr);
fill_stag(stag_header_kernel, kernel_info.file_size);
ret = write_fw(ofname, buf, writelen);
if (ret)
goto out_free_buf;
ret = EXIT_SUCCESS;
out_free_buf:
free(buf);
out:
return ret;
}
int wrap_fw(void)
{
char *buf;
char *image_ptr;
int ret = EXIT_FAILURE;
int writelen;
struct auh_header *auh_header_kernel;
if (!image_info.file_name)
goto out;
ret = get_file_stat(&image_info);
if (ret)
goto out;
buf = malloc(firmware_size);
if (!buf) {
ERR("no memory for buffer\n");
goto out;
}
if (image_info.file_size + AUH_SIZE >
firmware_size) {
ERR("data is bigger than firmware_size!\n");
goto out;
}
if (!family_member) {
ERR("No family_member!\n");
goto out;
}
if (!(rom_id[0])) {
ERR("No rom_id!\n");
goto out;
}
memset(buf, 0xff, firmware_size);
image_ptr = (char *)(buf + AUH_SIZE);
ret = read_to_buf(&image_info, image_ptr);
if (ret)
goto out_free_buf;
writelen = image_ptr + image_info.file_size - buf;
auh_header_kernel = (struct auh_header *)buf;
fill_auh(auh_header_kernel, writelen - AUH_SIZE);
ret = write_fw(ofname, buf, writelen);
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]);
image_type = SYSUPGRADE;
family_member = 0;
firmware_size = 0;
while (1) {
int c;
c = getopt(argc, argv, "f:F:i:hk:m:o:r:s:");
if (c == -1)
break;
switch (c) {
case 'f':
sscanf(optarg, "0x%hx", &family_member);
break;
case 'F':
image_info.file_name = optarg;
image_type = FACTORY;
break;
case 'i':
inspect_info.file_name = optarg;
break;
case 'k':
kernel_info.file_name = optarg;
break;
case 'm':
if (strlen(optarg) == 12)
memcpy(rom_id, optarg, 12);
break;
case 'r':
rootfs_info.file_name = optarg;
break;
case 'o':
ofname = optarg;
break;
case 's':
sscanf(optarg, "0x%x", &firmware_size);
break;
default:
usage(EXIT_FAILURE);
break;
}
}
ret = check_options();
if (ret)
goto out;
if (!inspect_info.file_name) {
if (image_type == FACTORY)
ret = wrap_fw();
else
ret = build_fw();
}
else
ret = inspect_fw();
out:
return ret;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,471 @@
/*
* 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= 0x00760000,
},
{
.name = "UBDEV01",
.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:"
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 (*p->name && (strcmp(p->name, board_name) != 0))
p++;
if (!*p->name) {
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)) == (u_int32_t)-1) 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;
}

View File

@@ -0,0 +1,451 @@
/*
* 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;
}
#ifndef STRINGIFY
#define STRINGIFY2(X) #X
#define STRINGIFY(X) STRINGIFY2(X)
#endif
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]:%"STRINGIFY(PATH_MAX)"s",
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;
}

View File

@@ -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);
}

Some files were not shown because too many files have changed in this diff Show More