Initial commit
This commit is contained in:
157
tools/Makefile
Normal file
157
tools/Makefile
Normal file
@@ -0,0 +1,157 @@
|
||||
#
|
||||
# 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
|
||||
tools-$(CONFIG_TARGET_ar71xx)$(CONFIG_TARGET_ath79) += squashfs
|
||||
tools-$(CONFIG_USES_MINOR) += kernel2minor
|
||||
tools-y += lzma squashfskit4 zip
|
||||
tools-$(BUILD_B43_TOOLS) += b43-tools
|
||||
tools-$(BUILD_ISL) += isl
|
||||
tools-$(CONFIG_USE_SPARSE) += sparse
|
||||
tools-$(CONFIG_TARGET_apm821xx)$(CONFIG_TARGET_gemini) += genext2fs
|
||||
tools-$(CONFIG_TARGET_tegra) += cbootimage cbootimage-configs
|
||||
|
||||
# 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)/squashfskit4/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
|
||||
$(curdir)/cbootimage/compile += $(curdir)/automake/compile
|
||||
|
||||
ifneq ($(HOST_OS),Linux)
|
||||
$(curdir)/squashfskit4/compile += $(curdir)/coreutils/compile
|
||||
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, $(filter-out xz,$(tools-core)), $(eval $(curdir)/$(tool)/compile += $(curdir)/sed/compile))
|
||||
$(curdir)/xz/compile += $(curdir)/flock/compile
|
||||
|
||||
$(curdir)/sed/compile := $(curdir)/flock/compile $(curdir)/xz/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 usr/include usr/lib; \
|
||||
); 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
37
tools/autoconf/Makefile
Normal 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))
|
||||
229
tools/autoconf/patches/000-relocatable.patch
Normal file
229
tools/autoconf/patches/000-relocatable.patch
Normal 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
|
||||
22
tools/autoconf/patches/001-no_emacs_lib.patch
Normal file
22
tools/autoconf/patches/001-no_emacs_lib.patch
Normal 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 \
|
||||
24
tools/autoconf/patches/002-musl_host_fixup.patch
Normal file
24
tools/autoconf/patches/002-musl_host_fixup.patch
Normal 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
51
tools/automake/Makefile
Normal 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
2
tools/automake/files/aclocal
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env sh
|
||||
aclocal.real $ACLOCAL_INCLUDE $@
|
||||
96
tools/automake/patches/000-relocatable.patch
Normal file
96
tools/automake/patches/000-relocatable.patch
Normal 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
|
||||
@@ -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?
|
||||
@@ -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
50
tools/b43-tools/Makefile
Normal 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_DATE:=2017-09-13
|
||||
|
||||
PKG_SOURCE_URL:=https://github.com/mbuesch/b43-tools.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
||||
PKG_SOURCE_VERSION:=27892ef741e7f1d08cb939744f8b8f5dac7b04ae
|
||||
PKG_MIRROR_HASH:=f914c36ac566e9e3b5a3a04de16ddb014fcad6a1cf25cdd8e4825c708d28d3f4
|
||||
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))
|
||||
149
tools/b43-tools/files/b43-fwsquash.py
Executable file
149
tools/b43-tools/files/b43-fwsquash.py
Executable 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)
|
||||
|
||||
16
tools/b43-tools/patches/001-fw-dirname.patch
Normal file
16
tools/b43-tools/patches/001-fw-dirname.patch
Normal 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;
|
||||
|
||||
14
tools/b43-tools/patches/002-no_libfl.patch
Normal file
14
tools/b43-tools/patches/002-no_libfl.patch
Normal 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
21
tools/bc/Makefile
Normal 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))
|
||||
23
tools/bc/patches/001-no_doc.patch
Normal file
23
tools/bc/patches/001-no_doc.patch
Normal 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
|
||||
|
||||
32
tools/bison/Makefile
Normal file
32
tools/bison/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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.4.1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
|
||||
PKG_HASH:=27159ac5ebf736dffd5636fd2cd625767c9e437de65baa63cb0de83570bd820d
|
||||
|
||||
HOST_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
HOST_CONFIGURE_ARGS += --enable-threads=pth
|
||||
|
||||
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))
|
||||
17
tools/bison/patches/100-fix-gets-removal.patch
Normal file
17
tools/bison/patches/100-fix-gets-removal.patch
Normal file
@@ -0,0 +1,17 @@
|
||||
--- a/lib/stdio.in.h
|
||||
+++ b/lib/stdio.in.h
|
||||
@@ -746,14 +746,6 @@ _GL_WARN_ON_USE (getline, "getline is un
|
||||
# endif
|
||||
#endif
|
||||
|
||||
-/* It is very rare that the developer ever has full control of stdin,
|
||||
- so any use of gets warrants an unconditional warning; besides, C11
|
||||
- removed it. */
|
||||
-#undef gets
|
||||
-#if HAVE_RAW_DECL_GETS && !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
2
tools/bison/scripts/yacc
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec bison -y "$@"
|
||||
32
tools/cbootimage-configs/Makefile
Normal file
32
tools/cbootimage-configs/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# Copyright (c) 2017-2019 Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME := cbootimage-configs
|
||||
|
||||
PKG_SOURCE_DATE := 2017-04-13
|
||||
PKG_SOURCE_PROTO := git
|
||||
PKG_SOURCE_URL := https://github.com/NVIDIA/cbootimage-configs.git
|
||||
PKG_SOURCE_VERSION := 7c3b458b93ed6947cd083623f543e93f9103cc0f
|
||||
PKG_MIRROR_HASH := 1d24421af8cf74ec2d625e237aa8121b1273774c4380ad333e2954e052a5a4fe
|
||||
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Host/Compile
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_DIR) $(STAGING_DIR_HOST)/share/$(PKG_NAME)
|
||||
$(CP) $(HOST_BUILD_DIR)/* \
|
||||
$(STAGING_DIR_HOST)/share/$(PKG_NAME)
|
||||
endef
|
||||
|
||||
define Host/Clean
|
||||
rm -fR $(STAGING_DIR_HOST)/share/$(PKG_NAME)
|
||||
endef
|
||||
|
||||
$(eval $(call HostBuild))
|
||||
31
tools/cbootimage/Makefile
Normal file
31
tools/cbootimage/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Copyright (c) 2017-2019 Tomasz Maciej Nowak <tomek_n@o2.pl>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME := cbootimage
|
||||
PKG_VERSION := 1.8
|
||||
|
||||
PKG_SOURCE_PROTO := git
|
||||
PKG_SOURCE_URL := https://github.com/NVIDIA/cbootimage.git
|
||||
PKG_SOURCE_VERSION := 7c9db585d06cce9efffa2a82245f233233680060
|
||||
PKG_MIRROR_HASH := 84d9abaaa3eddde05f506dc16effe1c9e18eb94727ed59c5e0a879baeb04e0b2
|
||||
|
||||
HOST_BUILD_PARALLEL := 1
|
||||
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Host/Configure
|
||||
(cd $(HOST_BUILD_DIR); autoreconf --install --symlink)
|
||||
$(call Host/Configure/Default)
|
||||
endef
|
||||
|
||||
define Host/Clean
|
||||
rm -f $(STAGING_DIR_HOST)/bin/$(PKG_NAME) \
|
||||
$(STAGING_DIR_HOST)/share/man/man1/$(PKG_NAME).1
|
||||
endef
|
||||
|
||||
$(eval $(call HostBuild))
|
||||
35
tools/ccache/Makefile
Normal file
35
tools/ccache/Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (C) 2006-2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
PKG_NAME:=ccache
|
||||
PKG_VERSION:=3.7.2
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=https://github.com/ccache/ccache/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=a5da0008512ff9e882097acaffb3616fae98ec25827167bb4bd1e4acf0b66793
|
||||
|
||||
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
2
tools/ccache/files/ccache_cc
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec ccache "${TARGET_CC_NOCACHE}" "$@"
|
||||
2
tools/ccache/files/ccache_cxx
Executable file
2
tools/ccache/files/ccache_cxx
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec ccache "${TARGET_CXX_NOCACHE}" "$@"
|
||||
10
tools/ccache/patches/100-honour-copts.patch
Normal file
10
tools/ccache/patches/100-honour-copts.patch
Normal file
@@ -0,0 +1,10 @@
|
||||
--- a/src/ccache.c
|
||||
+++ b/src/ccache.c
|
||||
@@ -2189,6 +2189,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) {
|
||||
50
tools/cmake/Makefile
Normal file
50
tools/cmake/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# 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.15.1
|
||||
PKG_RELEASE:=2
|
||||
PKG_CPE_ID:=cpe:/a:kitware:cmake
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/Kitware/CMake/releases/download/v$(PKG_VERSION)/ \
|
||||
https://cmake.org/files/v3.15/
|
||||
PKG_HASH:=18dec548d8f8b04d53c60f9cedcebaa6762f8425339d1e2c889c383d3ccdd7f7
|
||||
|
||||
HOST_BUILD_PARALLEL:=1
|
||||
HOST_CONFIGURE_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
# Workaround for GCC versions below 6.X and ccache
|
||||
# Reference: https://github.com/openwrt/openwrt/pull/1929
|
||||
GCC_DMPVER_GREPCMD := grep -E '^(4\.[8-9]|[5]\.?)'
|
||||
GCC_DMPVER_STRING := $(shell $(HOSTCC_NOCACHE) -dumpversion | $(GCC_DMPVER_GREPCMD))
|
||||
ifneq ($(GCC_DMPVER_STRING),)
|
||||
ifeq ($(CONFIG_CCACHE),y)
|
||||
$(info GCC version less than 6.0 detected, disabling CCACHE)
|
||||
HOST_CONFIGURE_VARS:=$(filter-out CC=% gcc%",$(HOST_CONFIGURE_VARS)) CC="$(HOSTCC_NOCACHE)"
|
||||
HOST_CONFIGURE_VARS:=$(filter-out CXX=% g++%",$(HOST_CONFIGURE_VARS)) CXX="$(HOSTCXX_NOCACHE)"
|
||||
else
|
||||
$(info GCC version greater or equal to 6.0 detected, no workaround set for CCACHE)
|
||||
endif
|
||||
endif
|
||||
|
||||
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))
|
||||
34
tools/cmake/patches/100-disable_qt_tests.patch
Normal file
34
tools/cmake/patches/100-disable_qt_tests.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
--- a/Tests/RunCMake/CMakeLists.txt
|
||||
+++ b/Tests/RunCMake/CMakeLists.txt
|
||||
@@ -325,15 +325,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
|
||||
@@ -483,13 +483,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"
|
||||
11
tools/cmake/patches/110-libarchive-fix-libressl-compat.patch
Normal file
11
tools/cmake/patches/110-libarchive-fix-libressl-compat.patch
Normal 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)
|
||||
37
tools/cmake/patches/120-curl-fix-libressl-linking.patch
Normal file
37
tools/cmake/patches/120-curl-fix-libressl-linking.patch
Normal 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
|
||||
@@ -453,6 +453,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})
|
||||
|
||||
14
tools/cmake/patches/130-bootstrap_parallel_make_flag.patch
Normal file
14
tools/cmake/patches/130-bootstrap_parallel_make_flag.patch
Normal file
@@ -0,0 +1,14 @@
|
||||
--- a/bootstrap
|
||||
+++ b/bootstrap
|
||||
@@ -1168,7 +1168,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
|
||||
25
tools/cmake/patches/140-libarchive-fix-libressl.patch
Normal file
25
tools/cmake/patches/140-libarchive-fix-libressl.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
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_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
37
tools/coreutils/Makefile
Normal 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))
|
||||
25
tools/coreutils/patches/001-fix-macos-vasnprintf.patch
Normal file
25
tools/coreutils/patches/001-fix-macos-vasnprintf.patch
Normal 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
27
tools/dosfstools/Makefile
Normal 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))
|
||||
@@ -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])
|
||||
53
tools/e2fsprogs/Makefile
Normal file
53
tools/e2fsprogs/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# 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.45.4
|
||||
PKG_HASH:=65faf6b590ca1da97440d6446bd11de9e0914b42553740ba5d9d2a796fa0dc02
|
||||
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
|
||||
|
||||
ifneq ($(shell $(HOSTCC) --version | grep clang),)
|
||||
HOST_CFLAGS += -D__GNUC_PREREQ\(...\)=0
|
||||
endif
|
||||
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))
|
||||
11
tools/e2fsprogs/patches/001-exit_0_on_corrected_errors.patch
Normal file
11
tools/e2fsprogs/patches/001-exit_0_on_corrected_errors.patch
Normal 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 */
|
||||
11
tools/e2fsprogs/patches/002-dont-build-e4defrag.patch
Normal file
11
tools/e2fsprogs/patches/002-dont-build-e4defrag.patch
Normal 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
|
||||
11
tools/e2fsprogs/patches/003-no-crond.patch
Normal file
11
tools/e2fsprogs/patches/003-no-crond.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -14525,7 +14525,7 @@ $as_echo_n "checking for system crontab
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${crond_dir}" >&5
|
||||
$as_echo "${crond_dir}" >&6; }
|
||||
- have_crond="yes"
|
||||
+ have_crond="no"; with_crond_dir=""
|
||||
|
||||
else
|
||||
|
||||
26
tools/elftosb/Makefile
Normal file
26
tools/elftosb/Makefile
Normal 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))
|
||||
11
tools/elftosb/patches/001-libm.patch
Normal file
11
tools/elftosb/patches/001-libm.patch
Normal 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")
|
||||
19
tools/elftosb/patches/002-fix-header-path.patch
Normal file
19
tools/elftosb/patches/002-fix-header-path.patch
Normal 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;
|
||||
26
tools/elftosb/patches/003-use-ldflags.patch
Normal file
26
tools/elftosb/patches/003-use-ldflags.patch
Normal 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
29
tools/expat/Makefile
Normal 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
21
tools/findutils/Makefile
Normal 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))
|
||||
13
tools/findutils/patches/100-include_sysmacros.patch
Normal file
13
tools/findutils/patches/100-include_sysmacros.patch
Normal 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>
|
||||
104
tools/findutils/patches/110-glibc-change-work-around.patch
Normal file
104
tools/findutils/patches/110-glibc-change-work-around.patch
Normal 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. */
|
||||
96
tools/firmware-utils/Makefile
Normal file
96
tools/firmware-utils/Makefile
Normal file
@@ -0,0 +1,96 @@
|
||||
#
|
||||
# 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,lxlfw)
|
||||
$(call cc,trx)
|
||||
$(call cc,otrx)
|
||||
$(call cc,motorola-bin)
|
||||
$(call cc,dgfirmware)
|
||||
$(call cc,mksenaofw md5, -Wall --std=gnu99)
|
||||
$(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,mkrasimage, --std=gnu99)
|
||||
$(call cc,mkhilinkfw, -lcrypto)
|
||||
$(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=c99)
|
||||
$(call cc,dns313-header, -Wall)
|
||||
$(call cc,mksercommfw, -Wall)
|
||||
$(call cc,nec-enc, -Wall --std=gnu99)
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_BIN) $(HOST_BUILD_DIR)/bin/* $(STAGING_DIR_HOST)/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call HostBuild))
|
||||
138
tools/firmware-utils/src/add_header.c
Normal file
138
tools/firmware-utils/src/add_header.c
Normal 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;
|
||||
}
|
||||
358
tools/firmware-utils/src/addpattern.c
Normal file
358
tools/firmware-utils/src/addpattern.c
Normal 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;
|
||||
}
|
||||
256
tools/firmware-utils/src/asustrx.c
Normal file
256
tools/firmware-utils/src/asustrx.c
Normal 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;
|
||||
}
|
||||
70
tools/firmware-utils/src/bcm_tag.h
Normal file
70
tools/firmware-utils/src/bcm_tag.h
Normal 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 */
|
||||
248
tools/firmware-utils/src/bcmalgo.c
Normal file
248
tools/firmware-utils/src/bcmalgo.c
Normal 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" );
|
||||
}
|
||||
83
tools/firmware-utils/src/bcmalgo.h
Normal file
83
tools/firmware-utils/src/bcmalgo.h
Normal 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 );
|
||||
322
tools/firmware-utils/src/buffalo-enc.c
Normal file
322
tools/firmware-utils/src/buffalo-enc.c
Normal 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;
|
||||
}
|
||||
480
tools/firmware-utils/src/buffalo-lib.c
Normal file
480
tools/firmware-utils/src/buffalo-lib.c
Normal 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;
|
||||
}
|
||||
141
tools/firmware-utils/src/buffalo-lib.h
Normal file
141
tools/firmware-utils/src/buffalo-lib.h
Normal 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 */
|
||||
414
tools/firmware-utils/src/buffalo-tag.c
Normal file
414
tools/firmware-utils/src/buffalo-tag.c
Normal 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;
|
||||
}
|
||||
177
tools/firmware-utils/src/buffalo-tftp.c
Normal file
177
tools/firmware-utils/src/buffalo-tftp.c
Normal 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;
|
||||
}
|
||||
79
tools/firmware-utils/src/csysimg.h
Normal file
79
tools/firmware-utils/src/csysimg.h
Normal 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;
|
||||
};
|
||||
109
tools/firmware-utils/src/cyg_crc.h
Normal file
109
tools/firmware-utils/src/cyg_crc.h
Normal 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_
|
||||
|
||||
|
||||
|
||||
110
tools/firmware-utils/src/cyg_crc16.c
Normal file
110
tools/firmware-utils/src/cyg_crc16.c
Normal 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;
|
||||
}
|
||||
|
||||
172
tools/firmware-utils/src/cyg_crc32.c
Normal file
172
tools/firmware-utils/src/cyg_crc32.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
377
tools/firmware-utils/src/dgfirmware.c
Normal file
377
tools/firmware-utils/src/dgfirmware.c
Normal 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;
|
||||
}
|
||||
|
||||
166
tools/firmware-utils/src/dgn3500sum.c
Normal file
166
tools/firmware-utils/src/dgn3500sum.c
Normal 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;
|
||||
}
|
||||
239
tools/firmware-utils/src/dns313-header.c
Normal file
239
tools/firmware-utils/src/dns313-header.c
Normal 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;
|
||||
}
|
||||
386
tools/firmware-utils/src/edimax_fw_header.c
Normal file
386
tools/firmware-utils/src/edimax_fw_header.c
Normal 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;
|
||||
}
|
||||
151
tools/firmware-utils/src/encode_crc.c
Normal file
151
tools/firmware-utils/src/encode_crc.c
Normal 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;
|
||||
}
|
||||
354
tools/firmware-utils/src/fix-u-media-header.c
Normal file
354
tools/firmware-utils/src/fix-u-media-header.c
Normal 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;
|
||||
}
|
||||
78
tools/firmware-utils/src/fw.h
Normal file
78
tools/firmware-utils/src/fw.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* * 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_ENDS "ENDS"
|
||||
|
||||
#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;
|
||||
|
||||
typedef struct signature_rsa {
|
||||
char magic[MAGIC_LENGTH];
|
||||
// u_int32_t crc;
|
||||
unsigned char rsa_signature[256];
|
||||
u_int32_t pad;
|
||||
} __attribute__ ((packed)) signature_rsa_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
|
||||
203
tools/firmware-utils/src/hcsmakeimage.c
Normal file
203
tools/firmware-utils/src/hcsmakeimage.c
Normal 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;
|
||||
}
|
||||
491
tools/firmware-utils/src/imagetag.c
Normal file
491
tools/firmware-utils/src/imagetag.c
Normal 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);
|
||||
}
|
||||
46
tools/firmware-utils/src/imagetag.ggo
Normal file
46
tools/firmware-utils/src/imagetag.ggo
Normal 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
|
||||
1193
tools/firmware-utils/src/imagetag_cmdline.c
Normal file
1193
tools/firmware-utils/src/imagetag_cmdline.c
Normal file
File diff suppressed because it is too large
Load Diff
275
tools/firmware-utils/src/imagetag_cmdline.h
Normal file
275
tools/firmware-utils/src/imagetag_cmdline.h
Normal 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 */
|
||||
437
tools/firmware-utils/src/jcgimage.c
Normal file
437
tools/firmware-utils/src/jcgimage.c
Normal file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* jcgimage - Create a JCG firmware image
|
||||
*
|
||||
* Copyright (C) 2015 Reinhard Max <reinhard@m4x.de>
|
||||
* Copyright (C) 2019 Davide Fioravanti <pantanastyle@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Using -m is possible to set the maximum size of the payload.
|
||||
* Otherwise the default MAXSIZE will be used.
|
||||
* For an 8Mb flash, the corresponding maxsize is:
|
||||
* 8 * 1024 * 1024 - 5 * 64 * 1024 = 8388608 - 327680 = 8060928
|
||||
*
|
||||
* 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>
|
||||
#include <inttypes.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 [-m maxsize] [-v version]\n"
|
||||
"jcgimage -o outfile -k kernel -f rootfs [-m maxsize] [-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;
|
||||
size_t maxsize = MAXSIZE;
|
||||
char *endptr;
|
||||
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:m: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 'm':
|
||||
if (optarg != NULL)
|
||||
maxsize = strtoimax(optarg, &endptr, 10);
|
||||
|
||||
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;
|
||||
}
|
||||
282
tools/firmware-utils/src/lxlfw.c
Normal file
282
tools/firmware-utils/src/lxlfw.c
Normal file
@@ -0,0 +1,282 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
/*
|
||||
* Luxul's firmware container format
|
||||
*
|
||||
* Copyright 2020 Legrand AV Inc.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <stddef.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 cpu_to_le16(x) bswap_16(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#define le16_to_cpu(x) bswap_16(x)
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#define le16_to_cpu(x) (x)
|
||||
#endif
|
||||
|
||||
#define min(a, b) \
|
||||
({ \
|
||||
__typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define max(a, b) \
|
||||
({ \
|
||||
__typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define LXL_FLAGS_VENDOR_LUXUL 0x00000001
|
||||
|
||||
struct lxl_hdr {
|
||||
char magic[4]; /* "LXL#" */
|
||||
uint32_t version;
|
||||
uint32_t hdr_len;
|
||||
uint8_t v0_end[0];
|
||||
/* Version: 1+ */
|
||||
uint32_t flags;
|
||||
char board[16];
|
||||
uint8_t v1_end[0];
|
||||
/* Version: 2+ */
|
||||
uint8_t release[4];
|
||||
uint8_t v2_end[0];
|
||||
} __packed;
|
||||
|
||||
static uint32_t lxlfw_hdr_len(uint32_t version)
|
||||
{
|
||||
switch (version) {
|
||||
case 0:
|
||||
return offsetof(struct lxl_hdr, v0_end);
|
||||
case 1:
|
||||
return offsetof(struct lxl_hdr, v1_end);
|
||||
case 2:
|
||||
return offsetof(struct lxl_hdr, v2_end);
|
||||
default:
|
||||
fprintf(stderr, "Unsupported version %d\n", version);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Info
|
||||
**************************************************/
|
||||
|
||||
static int lxlfw_info(int argc, char **argv) {
|
||||
struct lxl_hdr hdr;
|
||||
uint32_t version;
|
||||
uint32_t hdr_len;
|
||||
char board[17];
|
||||
size_t bytes;
|
||||
int err = 0;
|
||||
FILE *lxl;
|
||||
int flags;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Missing <file> argument\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lxl = fopen(argv[2], "r");
|
||||
if (!lxl) {
|
||||
fprintf(stderr, "Could not open \"%s\" file\n", argv[2]);
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes = fread(&hdr, 1, sizeof(hdr), lxl);
|
||||
if (bytes < offsetof(struct lxl_hdr, v0_end)) {
|
||||
fprintf(stderr, "Input file too small to use Luxul format\n");
|
||||
err = -ENXIO;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (memcmp(hdr.magic, "LXL#", 4)) {
|
||||
fprintf(stderr, "File <file> does not use Luxul's format\n");
|
||||
err = -EINVAL;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
version = le32_to_cpu(hdr.version);
|
||||
hdr_len = lxlfw_hdr_len(version);
|
||||
if (bytes < hdr_len) {
|
||||
fprintf(stderr, "Input file too small for header version %d\n", version);
|
||||
err = -ENXIO;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
printf("Format version:\t%d\n", version);
|
||||
printf("Header length:\t%d\n", le32_to_cpu(hdr.hdr_len));
|
||||
if (version >= 1) {
|
||||
printf("Flags:\t\t");
|
||||
flags = le32_to_cpu(hdr.flags);
|
||||
if (flags & LXL_FLAGS_VENDOR_LUXUL)
|
||||
printf("VENDOR_LUXUL ");
|
||||
printf("\n");
|
||||
memcpy(board, hdr.board, sizeof(hdr.board));
|
||||
board[16] = '\0';
|
||||
printf("Board:\t\t%s\n", board);
|
||||
}
|
||||
if (version >= 2) {
|
||||
printf("Release:\t");
|
||||
if (hdr.release[0] || hdr.release[1] || hdr.release[2] || hdr.release[3]) {
|
||||
printf("%hu.%hu.%hu", hdr.release[0], hdr.release[1], hdr.release[2]);
|
||||
if (hdr.release[3])
|
||||
printf(".%hu", hdr.release[3]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
err_close:
|
||||
fclose(lxl);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Create
|
||||
**************************************************/
|
||||
|
||||
static int lxlfw_create(int argc, char **argv) {
|
||||
struct lxl_hdr hdr = {
|
||||
.magic = { 'L', 'X', 'L', '#' },
|
||||
};
|
||||
char *in_path = NULL;
|
||||
uint32_t version = 0;
|
||||
uint32_t hdr_len;
|
||||
ssize_t bytes;
|
||||
char buf[512];
|
||||
int err = 0;
|
||||
FILE *lxl;
|
||||
FILE *in;
|
||||
int c;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Missing <file> argument\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
optind = 3;
|
||||
while ((c = getopt(argc, argv, "i:lb:r:")) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
in_path = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
hdr.flags |= cpu_to_le32(LXL_FLAGS_VENDOR_LUXUL);
|
||||
version = max(version, 1);
|
||||
break;
|
||||
case 'b':
|
||||
memcpy(hdr.board, optarg, strlen(optarg) > 16 ? 16 : strlen(optarg));
|
||||
version = max(version, 1);
|
||||
break;
|
||||
case 'r':
|
||||
if (sscanf(optarg, "%hhu.%hhu.%hhu.%hhu", &hdr.release[0], &hdr.release[1], &hdr.release[2], &hdr.release[3]) < 1) {
|
||||
fprintf(stderr, "Failed to parse release number \"%s\"\n", optarg);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
version = max(version, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hdr.version = cpu_to_le32(version);
|
||||
hdr_len = lxlfw_hdr_len(version);
|
||||
if (!hdr_len) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
hdr.hdr_len = cpu_to_le32(hdr_len);
|
||||
|
||||
if (!in_path) {
|
||||
fprintf(stderr, "Missing input file argument\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
in = fopen(in_path, "r");
|
||||
if (!in) {
|
||||
fprintf(stderr, "Could not open input file %s\n", in_path);
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lxl = fopen(argv[2], "w+");
|
||||
if (!lxl) {
|
||||
fprintf(stderr, "Could not open \"%s\" file\n", argv[2]);
|
||||
err = -EIO;
|
||||
goto err_close_in;
|
||||
}
|
||||
|
||||
bytes = fwrite(&hdr, 1, hdr_len, lxl);
|
||||
if (bytes != hdr_len) {
|
||||
fprintf(stderr, "Could not write Luxul's header\n");
|
||||
err = -EIO;
|
||||
goto err_close_lxl;
|
||||
}
|
||||
|
||||
while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
|
||||
if (fwrite(buf, 1, bytes, lxl) != bytes) {
|
||||
fprintf(stderr, "Could not copy %zu bytes from input file\n", bytes);
|
||||
err = -EIO;
|
||||
goto err_close_lxl;
|
||||
}
|
||||
}
|
||||
|
||||
err_close_lxl:
|
||||
fclose(lxl);
|
||||
err_close_in:
|
||||
fclose(in);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Start
|
||||
**************************************************/
|
||||
|
||||
static void usage() {
|
||||
printf("Usage:\n");
|
||||
printf("\n");
|
||||
printf("Get info about Luxul firmware:\n");
|
||||
printf("\tlxlfw info <file>\n");
|
||||
printf("\n");
|
||||
printf("Create new Luxul firmware:\n");
|
||||
printf("\tlxlfw create <file> [options]\n");
|
||||
printf("\t-i file\t\t\t\tinput file for Luxul's firmware container\n");
|
||||
printf("\t-l\t\t\t\tmark firmware as created by Luxul company (DON'T USE)\n");
|
||||
printf("\t-b board\t\t\tboard (device) name\n");
|
||||
printf("\t-r release\t\t\trelease number (e.g. 5.1.0, 7.1.0.2)\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "info"))
|
||||
return lxlfw_info(argc, argv);
|
||||
else if (!strcmp(argv[1], "create"))
|
||||
return lxlfw_create(argc, argv);
|
||||
}
|
||||
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
190
tools/firmware-utils/src/lzma2eva.c
Normal file
190
tools/firmware-utils/src/lzma2eva.c
Normal 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;
|
||||
}
|
||||
316
tools/firmware-utils/src/makeamitbin.c
Normal file
316
tools/firmware-utils/src/makeamitbin.c
Normal 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;
|
||||
}
|
||||
296
tools/firmware-utils/src/md5.c
Normal file
296
tools/firmware-utils/src/md5.c
Normal 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
|
||||
45
tools/firmware-utils/src/md5.h
Normal file
45
tools/firmware-utils/src/md5.h
Normal 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
|
||||
168
tools/firmware-utils/src/mkbrncmdline.c
Normal file
168
tools/firmware-utils/src/mkbrncmdline.c
Normal 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;
|
||||
}
|
||||
189
tools/firmware-utils/src/mkbrnimg.c
Normal file
189
tools/firmware-utils/src/mkbrnimg.c
Normal 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;
|
||||
}
|
||||
223
tools/firmware-utils/src/mkbuffaloimg.c
Normal file
223
tools/firmware-utils/src/mkbuffaloimg.c
Normal 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;
|
||||
}
|
||||
433
tools/firmware-utils/src/mkcameofw.c
Normal file
433
tools/firmware-utils/src/mkcameofw.c
Normal 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;
|
||||
}
|
||||
|
||||
1030
tools/firmware-utils/src/mkcasfw.c
Normal file
1030
tools/firmware-utils/src/mkcasfw.c
Normal file
File diff suppressed because it is too large
Load Diff
341
tools/firmware-utils/src/mkchkimg.c
Normal file
341
tools/firmware-utils/src/mkchkimg.c
Normal 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;
|
||||
}
|
||||
|
||||
1157
tools/firmware-utils/src/mkcsysimg.c
Normal file
1157
tools/firmware-utils/src/mkcsysimg.c
Normal file
File diff suppressed because it is too large
Load Diff
226
tools/firmware-utils/src/mkdapimg.c
Normal file
226
tools/firmware-utils/src/mkdapimg.c
Normal 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(®ion, 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);
|
||||
}
|
||||
204
tools/firmware-utils/src/mkdapimg2.c
Normal file
204
tools/firmware-utils/src/mkdapimg2.c
Normal 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;
|
||||
}
|
||||
85
tools/firmware-utils/src/mkdhpimg.c
Normal file
85
tools/firmware-utils/src/mkdhpimg.c
Normal 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;
|
||||
}
|
||||
151
tools/firmware-utils/src/mkdlinkfw-lib.c
Normal file
151
tools/firmware-utils/src/mkdlinkfw-lib.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
uint32_t jboot_timestamp(void)
|
||||
{
|
||||
char *env = getenv("SOURCE_DATE_EPOCH");
|
||||
char *endptr = env;
|
||||
time_t fixed_timestamp = -1;
|
||||
errno = 0;
|
||||
|
||||
if (env && *env) {
|
||||
fixed_timestamp = strtoull(env, &endptr, 10);
|
||||
|
||||
if (errno || (endptr && *endptr != '\0')) {
|
||||
fprintf(stderr, "Invalid SOURCE_DATE_EPOCH");
|
||||
fixed_timestamp = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed_timestamp == -1)
|
||||
time(&fixed_timestamp);
|
||||
|
||||
return (((uint32_t) fixed_timestamp) - 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;
|
||||
size_t read;
|
||||
|
||||
f = fopen(fdata->file_name, "r");
|
||||
if (f == NULL) {
|
||||
ERRS("could not open \"%s\" for reading", fdata->file_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
read = fread(buf, fdata->file_size, 1, f);
|
||||
if (ferror(f) || read != 1) {
|
||||
ERRS("unable to read from file \"%s\"", fdata->file_name);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
|
||||
out_close:
|
||||
fclose(f);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
84
tools/firmware-utils/src/mkdlinkfw-lib.h
Normal file
84
tools/firmware-utils/src/mkdlinkfw-lib.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* compression type values in the header
|
||||
* so far onlysupport for LZMA is added
|
||||
*/
|
||||
#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 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 write_fw(const char *ofname, const char *data, int len);
|
||||
|
||||
#endif /* mkdlinkfw_lib_h */
|
||||
668
tools/firmware-utils/src/mkdlinkfw.c
Normal file
668
tools/firmware-utils/src/mkdlinkfw.c
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
* 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;
|
||||
uint32_t image_offset;
|
||||
uint16_t family_member;
|
||||
char *rom_id[12] = { 0 };
|
||||
char image_type;
|
||||
|
||||
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 =
|
||||
image_offset + 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 = image_offset;
|
||||
header->erase_length = firmware_size;
|
||||
header->data_offset = image_offset;
|
||||
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;
|
||||
image_offset = JBOOT_SIZE;
|
||||
|
||||
while (1) {
|
||||
int c;
|
||||
|
||||
c = getopt(argc, argv, "f:F:i:hk:m:o: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':
|
||||
sscanf(optarg, "0x%x", &image_offset);
|
||||
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;
|
||||
|
||||
}
|
||||
208
tools/firmware-utils/src/mkdniimg.c
Normal file
208
tools/firmware-utils/src/mkdniimg.c
Normal 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;
|
||||
}
|
||||
286
tools/firmware-utils/src/mkedimaximg.c
Normal file
286
tools/firmware-utils/src/mkedimaximg.c
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
# define HOST_TO_LE16(x) (x)
|
||||
# define HOST_TO_LE32(x) (x)
|
||||
# define HOST_TO_BE16(x) bswap_16(x)
|
||||
# define HOST_TO_BE32(x) bswap_32(x)
|
||||
#else
|
||||
# define HOST_TO_LE16(x) bswap_16(x)
|
||||
# define HOST_TO_LE32(x) bswap_32(x)
|
||||
# define HOST_TO_BE16(x) (x)
|
||||
# define HOST_TO_BE32(x) (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 int force_be = FALSE;
|
||||
|
||||
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"
|
||||
" -b big-endianness mode\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++) {
|
||||
if (force_be == FALSE)
|
||||
ret -= ((unsigned short *) buf->start)[i];
|
||||
else
|
||||
ret -= HOST_TO_BE16(((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:b")) != -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;
|
||||
case 'b':
|
||||
force_be = TRUE;
|
||||
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);
|
||||
|
||||
if (force_be == FALSE) {
|
||||
header.flash = HOST_TO_LE32(header.flash);
|
||||
header.size = HOST_TO_LE32(obuf.size - sizeof(struct header));
|
||||
header.start = HOST_TO_LE32(header.start);
|
||||
} else {
|
||||
header.flash = HOST_TO_BE32(header.flash);
|
||||
header.size = HOST_TO_BE32(obuf.size - sizeof(struct header));
|
||||
header.start = HOST_TO_BE32(header.start);
|
||||
}
|
||||
|
||||
memcpy (obuf.start, &header, sizeof(struct header));
|
||||
|
||||
if (force_be == FALSE)
|
||||
csum = HOST_TO_LE16(fwcsum(&ibuf));
|
||||
else
|
||||
csum = HOST_TO_BE16(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;
|
||||
}
|
||||
545
tools/firmware-utils/src/mkfwimage.c
Normal file
545
tools/firmware-utils/src/mkfwimage.c
Normal file
@@ -0,0 +1,545 @@
|
||||
/*
|
||||
* 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 <stdbool.h>
|
||||
#include "fw.h"
|
||||
|
||||
typedef struct fw_layout_data {
|
||||
u_int32_t kern_start;
|
||||
u_int32_t kern_entry;
|
||||
u_int32_t firmware_max_length;
|
||||
} fw_layout_t;
|
||||
|
||||
struct fw_info {
|
||||
char name[PATH_MAX];
|
||||
struct fw_layout_data fw_layout;
|
||||
bool sign;
|
||||
};
|
||||
|
||||
struct fw_info fw_info[] = {
|
||||
{
|
||||
.name = "XS2",
|
||||
.fw_layout = {
|
||||
.kern_start = 0xbfc30000,
|
||||
.kern_entry = 0x80041000,
|
||||
.firmware_max_length= 0x00390000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "XS5",
|
||||
.fw_layout = {
|
||||
.kern_start = 0xbe030000,
|
||||
.kern_entry = 0x80041000,
|
||||
.firmware_max_length= 0x00390000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "RS",
|
||||
.fw_layout = {
|
||||
.kern_start = 0xbf030000,
|
||||
.kern_entry = 0x80060000,
|
||||
.firmware_max_length= 0x00B00000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "RSPRO",
|
||||
.fw_layout = {
|
||||
.kern_start = 0xbf030000,
|
||||
.kern_entry = 0x80060000,
|
||||
.firmware_max_length= 0x00F00000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "LS-SR71",
|
||||
.fw_layout = {
|
||||
.kern_start = 0xbf030000,
|
||||
.kern_entry = 0x80060000,
|
||||
.firmware_max_length= 0x00640000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "XS2-8",
|
||||
.fw_layout = {
|
||||
.kern_start = 0xa8030000,
|
||||
.kern_entry = 0x80041000,
|
||||
.firmware_max_length= 0x006C0000,
|
||||
},
|
||||
.sign = false,
|
||||
|
||||
},
|
||||
{
|
||||
.name = "XM",
|
||||
.fw_layout = {
|
||||
.kern_start = 0x9f050000,
|
||||
.kern_entry = 0x80002000,
|
||||
.firmware_max_length= 0x00760000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "UBDEV01",
|
||||
.fw_layout = {
|
||||
.kern_start = 0x9f050000,
|
||||
.kern_entry = 0x80002000,
|
||||
.firmware_max_length= 0x006A0000,
|
||||
},
|
||||
.sign = false,
|
||||
},
|
||||
{
|
||||
.name = "WA",
|
||||
.fw_layout = {
|
||||
.kern_start = 0x9f050000,
|
||||
.kern_entry = 0x80002000,
|
||||
.firmware_max_length= 0x00F60000,
|
||||
},
|
||||
.sign = true,
|
||||
},
|
||||
{
|
||||
.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];
|
||||
struct fw_info* fwinfo;
|
||||
} image_info_t;
|
||||
|
||||
static struct fw_info* get_fwinfo(char* board_name) {
|
||||
struct fw_info *fwinfo = fw_info;
|
||||
while(strlen(fwinfo->name)) {
|
||||
if(strcmp(fwinfo->name, board_name) == 0) {
|
||||
return fwinfo;
|
||||
}
|
||||
fwinfo++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 void write_signature_rsa(void* mem, u_int32_t sig_offset)
|
||||
{
|
||||
/* write signature */
|
||||
signature_rsa_t* sign = (signature_rsa_t*)(mem + sig_offset);
|
||||
memset(sign, 0, sizeof(signature_rsa_t));
|
||||
|
||||
memcpy(sign->magic, MAGIC_ENDS, 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 = &im->fwinfo->fw_layout;
|
||||
|
||||
printf("board = %s\n", im->fwinfo->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);
|
||||
if(im->fwinfo->sign) {
|
||||
mem_size += sizeof(signature_rsa_t);
|
||||
} else {
|
||||
mem_size += 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
|
||||
if(im->fwinfo->sign) {
|
||||
write_signature_rsa(mem, mem_size - sizeof(signature_rsa_t));
|
||||
} else {
|
||||
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;
|
||||
struct fw_info *fwinfo;
|
||||
|
||||
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 ((fwinfo = get_fwinfo(board_name)) == NULL) {
|
||||
ERROR("Invalid baord name '%s'\n", board_name);
|
||||
usage(argv[0]);
|
||||
return -2;
|
||||
}
|
||||
|
||||
im.fwinfo = fwinfo;
|
||||
|
||||
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;
|
||||
}
|
||||
451
tools/firmware-utils/src/mkfwimage2.c
Normal file
451
tools/firmware-utils/src/mkfwimage2.c
Normal 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;
|
||||
}
|
||||
211
tools/firmware-utils/src/mkheader_gemtek.c
Normal file
211
tools/firmware-utils/src/mkheader_gemtek.c
Normal 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);
|
||||
}
|
||||
323
tools/firmware-utils/src/mkhilinkfw.c
Normal file
323
tools/firmware-utils/src/mkhilinkfw.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Jeff Kent <jeff@jkent.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* This tool encrypts and decrypts uImage formatted firmware for Hilink
|
||||
* HLK-RM04 wireless modules. It will also truncate a dump of mtd6 and make
|
||||
* it an image suitable for flashing via the stock firmware upgrade page.
|
||||
*
|
||||
* Build instructions:
|
||||
* gcc -lcrypto hlkcrypt.c -o hlkcrypt
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <openssl/des.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DES_KEY "H@L9K*(3"
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
#endif
|
||||
|
||||
#define IH_MAGIC 0x27051956
|
||||
#define IH_NMLEN 32
|
||||
typedef struct image_header {
|
||||
uint32_t ih_magic; /* Image Header Magic Number */
|
||||
uint32_t ih_hcrc; /* Image Header CRC Checksum */
|
||||
uint32_t ih_time; /* Image Creation Timestamp */
|
||||
uint32_t ih_size; /* Image Data Size */
|
||||
uint32_t ih_load; /* Data Load Address */
|
||||
uint32_t ih_ep; /* Entry Point Address */
|
||||
uint32_t ih_dcrc; /* Image Data CRC Checksum */
|
||||
uint8_t ih_os; /* Operating System */
|
||||
uint8_t ih_arch; /* CPU architecture */
|
||||
uint8_t ih_type; /* Image Type */
|
||||
uint8_t ih_comp; /* Compression Type */
|
||||
uint8_t ih_name[IH_NMLEN]; /* Image Name */
|
||||
} image_header_t;
|
||||
|
||||
static int temp_fd = -1;
|
||||
static DES_key_schedule schedule;
|
||||
|
||||
static void show_usage(const char *arg0);
|
||||
static void exit_cleanup(void);
|
||||
static void copy_file(int src, int dst);
|
||||
static void do_encrypt(void *p, off_t len);
|
||||
static void do_decrypt(void *p, off_t len);
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int encrypt_opt = 0;
|
||||
int decrypt_opt = 0;
|
||||
int input_opt = 0;
|
||||
int output_opt = 0;
|
||||
char *input_filename = NULL;
|
||||
char *output_filename = NULL;
|
||||
|
||||
int input_fd;
|
||||
int output_fd;
|
||||
off_t file_len;
|
||||
char *p;
|
||||
char buf[sizeof(image_header_t) + 3];
|
||||
image_header_t *header;
|
||||
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{"encrypt", no_argument, 0, 'e'},
|
||||
{"decrypt", no_argument, 0, 'd'},
|
||||
{"input", required_argument, 0, 'i'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
int option_index = 0;
|
||||
int c = getopt_long(argc, argv, "dei:o:",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'd':
|
||||
decrypt_opt++;
|
||||
if (decrypt_opt > 1) {
|
||||
fprintf(stderr, "%s: decrypt may only be specified once\n",
|
||||
argv[0]);
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
encrypt_opt++;
|
||||
if (encrypt_opt > 1) {
|
||||
fprintf(stderr, "%s: encrypt may only be specified once\n",
|
||||
argv[0]);
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
input_opt++;
|
||||
if (input_opt > 1) {
|
||||
fprintf(stderr, "%s: only one input file may be specified\n",
|
||||
argv[0]);
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
if (strcmp("-", optarg) != 0) {
|
||||
input_filename = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
output_opt++;
|
||||
if (output_opt > 1) {
|
||||
fprintf(stderr, "%s: only one output file may be specified\n",
|
||||
argv[0]);
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
if (strcmp("-", optarg) != 0) {
|
||||
output_filename = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
exit(-1);
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if (decrypt_opt && encrypt_opt) {
|
||||
fprintf(stderr, "%s: decrypt and encrypt may not be used together\n",
|
||||
argv[0]);
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
|
||||
if (!decrypt_opt && !encrypt_opt) {
|
||||
fprintf(stderr, "%s: neither decrypt or encrypt were specified\n",
|
||||
argv[0]);
|
||||
show_usage(argv[0]);
|
||||
}
|
||||
|
||||
temp_fd = fileno(tmpfile());
|
||||
if (temp_fd < 0) {
|
||||
fprintf(stderr, "Can't create temporary file\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
atexit(exit_cleanup);
|
||||
DES_set_key_unchecked((const_DES_cblock *)DES_KEY, &schedule);
|
||||
|
||||
if (input_filename) {
|
||||
input_fd = open(input_filename, O_RDONLY);
|
||||
if (input_fd < 0) {
|
||||
fprintf(stderr, "Can't open %s for reading: %s\n", input_filename,
|
||||
strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
copy_file(input_fd, temp_fd);
|
||||
close(input_fd);
|
||||
}
|
||||
else {
|
||||
copy_file(STDIN_FILENO, temp_fd);
|
||||
}
|
||||
|
||||
file_len = lseek(temp_fd, 0, SEEK_CUR);
|
||||
if (file_len < 64) {
|
||||
fprintf(stderr, "Not enough data\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
p = mmap(0, file_len, PROT_READ|PROT_WRITE, MAP_SHARED, temp_fd, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (encrypt_opt) {
|
||||
header = (image_header_t *)p;
|
||||
off_t len = min(file_len,
|
||||
ntohl(header->ih_size) + sizeof(image_header_t));
|
||||
if (ntohl(header->ih_magic) != IH_MAGIC) {
|
||||
fprintf(stderr, "Header magic incorrect: "
|
||||
"expected 0x%08X, got 0x%08X\n",
|
||||
IH_MAGIC, ntohl(header->ih_magic));
|
||||
munmap(p, file_len);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
do_encrypt(p, len);
|
||||
munmap(p, file_len);
|
||||
if (len != file_len) {
|
||||
if (ftruncate(temp_fd, len) < 0) {
|
||||
fprintf(stderr, "ftruncate failed: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decrypt_opt) {
|
||||
off_t header_len = min(file_len, sizeof(image_header_t) + 3);
|
||||
memcpy(buf, p, header_len);
|
||||
do_decrypt(buf, header_len);
|
||||
header = (image_header_t *)buf;
|
||||
if (ntohl(header->ih_magic) != IH_MAGIC) {
|
||||
fprintf(stderr, "Header magic incorrect: "
|
||||
"expected 0x%08X, got 0x%08X\n",
|
||||
IH_MAGIC, ntohl(header->ih_magic));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
do_decrypt(p, file_len);
|
||||
munmap(p, file_len);
|
||||
}
|
||||
|
||||
lseek(temp_fd, 0, SEEK_SET);
|
||||
if (output_filename) {
|
||||
output_fd = creat(output_filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
if (output_fd < 0) {
|
||||
fprintf(stderr, "Can't open %s for writing: %s\n",
|
||||
output_filename, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
copy_file(temp_fd, output_fd);
|
||||
close(output_fd);
|
||||
}
|
||||
else {
|
||||
copy_file(temp_fd, STDOUT_FILENO);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_usage(const char *arg0)
|
||||
{
|
||||
fprintf(stderr, "usage: %s -d|-e [-i FILE] [-o FILE]\n\n", arg0);
|
||||
fprintf(stderr, "%-15s %s\n", "-d, --decrypt", "decrypt data");
|
||||
fprintf(stderr, "%-15s %s\n", "-e, --encrypt", "encrypt data");
|
||||
fprintf(stderr, "%-15s %s\n", "-i, --input", "intput file (defaults to stdin)");
|
||||
fprintf(stderr, "%-15s %s\n", "-o, --output", "output file (defaults to stdout)");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void exit_cleanup(void)
|
||||
{
|
||||
if (temp_fd >= 0) {
|
||||
close(temp_fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_file(int src, int dst)
|
||||
{
|
||||
char buf[4096];
|
||||
ssize_t size;
|
||||
|
||||
while ((size = read(src, buf, 4096)) > 0) {
|
||||
write(dst, buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_encrypt(void *p, off_t len)
|
||||
{
|
||||
DES_cblock *pblock;
|
||||
int num_blocks;
|
||||
|
||||
num_blocks = len / 8;
|
||||
pblock = (DES_cblock *) p;
|
||||
while (num_blocks--) {
|
||||
DES_ecb_encrypt(pblock, pblock, &schedule, DES_ENCRYPT);
|
||||
pblock++;
|
||||
}
|
||||
|
||||
num_blocks = (len - 3) / 8;
|
||||
pblock = (DES_cblock *) (p + 3);
|
||||
while (num_blocks--) {
|
||||
DES_ecb_encrypt(pblock, pblock, &schedule, DES_ENCRYPT);
|
||||
pblock++;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_decrypt(void *p, off_t len)
|
||||
{
|
||||
DES_cblock *pblock;
|
||||
int num_blocks;
|
||||
|
||||
num_blocks = (len - 3) / 8;
|
||||
pblock = (DES_cblock *) (p + 3);
|
||||
while (num_blocks--) {
|
||||
DES_ecb_encrypt(pblock, pblock, &schedule, DES_DECRYPT);
|
||||
pblock++;
|
||||
}
|
||||
|
||||
num_blocks = len / 8;
|
||||
pblock = (DES_cblock *) p;
|
||||
while (num_blocks--) {
|
||||
DES_ecb_encrypt(pblock, pblock, &schedule, DES_DECRYPT);
|
||||
pblock++;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user